Skip to content

Commit 785bc22

Browse files
committed
Change validation structure
Signed-off-by: Tushar Goel <tushar.goel.dav@gmail.com>
1 parent 0a165e2 commit 785bc22

File tree

5 files changed

+211
-280
lines changed

5 files changed

+211
-280
lines changed

etc/scripts/generate_validators.py

Lines changed: 43 additions & 88 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 import PackageURL
76-
from packageurl import normalize
7775
from packageurl.contrib.route import Router
7876
7977
"""
@@ -82,103 +80,79 @@
8280
8381
class TypeValidator:
8482
@classmethod
85-
def validate(cls, purl: PackageURL, strict=False):
83+
def validate(cls, purl, strict=False):
8684
if not strict:
8785
purl = cls.normalize(purl)
8886
8987
if cls.namespace_requirement == "prohibited" and purl.namespace:
9088
yield f"Namespace is prohibited for purl type: {cls.type!r}"
91-
92-
if not cls.namespace_case_sensitive and purl.namespace and purl.namespace.lower() != purl.name:
89+
90+
elif cls.namespace_requirement == "required" and not purl.namespace:
91+
yield f"Namespace is required for purl type: {cls.type!r}"
92+
93+
if (
94+
cls.namespace_case_sensitive
95+
and purl.namespace
96+
and purl.namespace.lower() != purl.namespace
97+
):
9398
yield f"Namespace is not lowercased for purl type: {cls.type!r}"
94-
95-
if not cls.name_case_sensitive and purl.name and purl.name.lower() != purl.name:
99+
100+
if cls.name_case_sensitive and purl.name and purl.name.lower() != purl.name:
96101
yield f"Name is not lowercased for purl type: {cls.type!r}"
97102
98103
if not cls.version_case_sensitive and purl.version and purl.version.lower() != purl.version:
99104
yield f"Version is not lowercased for purl type: {cls.type!r}"
100-
101-
yield from cls.validate_type(purl)
102-
103-
@classmethod
104-
def normalize_type(cls, type: str):
105-
return type
106-
107-
@classmethod
108-
def normalize_namespace(cls, namespace: str):
109-
return namespace
110-
111-
@classmethod
112-
def normalize_name(cls, name: str):
113-
return name
114105
115-
@classmethod
116-
def normalize_version(cls, version: str):
117-
return version
118-
119-
@classmethod
120-
def normalize_qualifiers(cls, qualifiers: dict):
121-
return qualifiers
122-
123-
@classmethod
124-
def normalize_subpath(cls, subpath: str):
125-
return subpath
106+
yield from cls.validate_type(purl, strict=strict)
126107
127108
@classmethod
128-
def normalize(cls, purl: PackageURL):
129-
type_norm, namespace_norm, name_norm, version_norm, qualifiers_norm, subpath_norm = normalize(purl.type,
130-
purl.namespace,
131-
purl.name,
132-
purl.version,
133-
purl.qualifiers,
134-
purl.subpath,
135-
encode=False,
109+
def normalize(cls, purl):
110+
from packageurl import PackageURL
111+
from packageurl import normalize
112+
113+
type_norm, namespace_norm, name_norm, version_norm, qualifiers_norm, subpath_norm = (
114+
normalize(
115+
purl.type,
116+
purl.namespace,
117+
purl.name,
118+
purl.version,
119+
purl.qualifiers,
120+
purl.subpath,
121+
encode=False,
122+
)
136123
)
137124
138125
return PackageURL(
139-
type = type_norm,
140-
namespace = namespace_norm,
141-
name = name_norm,
142-
version = version_norm,
143-
qualifiers = qualifiers_norm,
144-
subpath = subpath_norm,
126+
type=type_norm,
127+
namespace=namespace_norm,
128+
name=name_norm,
129+
version=version_norm,
130+
qualifiers=qualifiers_norm,
131+
subpath=subpath_norm,
145132
)
146133
147134
@classmethod
148-
def validate_type(cls, purl: PackageURL):
149-
yield from cls.validate_qualifiers(purl=purl)
150-
135+
def validate_type(cls, purl, strict=False):
136+
if strict:
137+
yield from cls.validate_qualifiers(purl=purl)
138+
151139
@classmethod
152-
def validate_qualifiers(cls, purl: PackageURL):
140+
def validate_qualifiers(cls, purl):
153141
if not purl.qualifiers:
154142
return
155-
143+
156144
purl_qualifiers_keys = set(purl.qualifiers.keys())
157145
allowed_qualifiers_set = cls.allowed_qualifiers
158146
159147
disallowed = purl_qualifiers_keys - allowed_qualifiers_set
160-
148+
161149
if disallowed:
162-
yield (f"Invalid qualifiers found: {', '.join(disallowed)}. "
150+
yield (
151+
f"Invalid qualifiers found: {', '.join(disallowed)}. "
163152
f"Allowed qualifiers are: {', '.join(allowed_qualifiers_set)}"
164153
)
165154
'''
166155

167-
def validate_qualifiers(allowed_qualifiers, purl: PackageURL):
168-
if not purl.qualifiers:
169-
return True
170-
171-
purl_qualifiers_keys = set(purl.qualifiers.keys())
172-
allowed_qualifiers_set = set(allowed_qualifiers)
173-
174-
disallowed = purl_qualifiers_keys - allowed_qualifiers_set
175-
176-
if disallowed:
177-
yield (f"Invalid qualifiers found: {', '.join(disallowed)}. "
178-
f"Allowed qualifiers are: {', '.join(allowed_qualifiers_set)}"
179-
)
180-
181-
182156

183157
TEMPLATE = """
184158
class {class_name}({validator_class}):
@@ -195,16 +169,6 @@ class {class_name}({validator_class}):
195169
purl_pattern = "{purl_pattern}"
196170
"""
197171

198-
TEMPLATE_NAME_RULES = '''
199-
@override
200-
@classmethod
201-
def normalize_name(cls, name: str):
202-
"""
203-
Normalize name according to type rules
204-
{rules}
205-
"""
206-
raise NotImplementedError()
207-
'''
208172

209173
def generate_validators():
210174
"""
@@ -260,24 +224,15 @@ def generate_validators():
260224
))
261225

262226
script_parts.append(type_validator)
263-
264-
# if name_normalization_rules:
265-
# name_overrides = get_name_norm_rules(name_normalization_rules)
266-
# script_parts.append(name_overrides)
267227

268228
script_parts.append(generate_validators_by_type(validators_by_type=validators_by_type))
269-
script_parts.append(attach_router(validators_by_type.values()))
229+
# script_parts.append(attach_router(validators_by_type.values()))
270230

271231
validate_script = base_dir / "src" / "packageurl" / "validate.py"
272232

273233
validate_script.write_text("\n".join(script_parts))
274234

275235

276-
def get_name_norm_rules(name_normalization_rules):
277-
rules = "\n".join(name_normalization_rules)
278-
return TEMPLATE_NAME_RULES.format(rules=rules)
279-
280-
281236
def generate_validators_by_type(validators_by_type):
282237
"""
283238
Return a python snippet that maps a type to it's TypeValidator class

src/packageurl/__init__.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
from urllib.parse import urlsplit as _urlsplit
3939

4040
from packageurl.contrib.route import NoRouteAvailable
41-
from packageurl.validate import validate_router
4241

4342
if TYPE_CHECKING:
4443
from collections.abc import Callable
@@ -473,13 +472,18 @@ def to_string(self, encode: bool | None = True) -> str:
473472

474473
return "".join(purl)
475474

476-
def validate(self) -> list[str]:
475+
def validate(self, strict: bool = False) -> list[str]:
477476
"""
478477
Validate this PackageURL object and return a list of validation error messages.
479478
"""
479+
from packageurl.validate import VALIDATORS_BY_TYPE
480+
480481
if self:
481482
try:
482-
messages = list(validate_router.process(self))
483+
validator_class = VALIDATORS_BY_TYPE.get(self.type)
484+
if not validator_class:
485+
return [f"Given type: {self.type} can not be validated"]
486+
messages = list(validator_class.validate(self, strict)) # type: ignore[no-untyped-call]
483487
return messages
484488
except NoRouteAvailable:
485489
return [f"Given type: {self.type} can not be validated"]

0 commit comments

Comments
 (0)