Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def get_matcher(cls, path, rule):
if "matchers" in rule:
# v3 matchingRules always have a matchers array, even if there's a single rule
return MultipleMatchers(path, **rule)
if "regex" in rule:
# there's a weirdness in the spec here: it promotes use of regex without a match type :(
type_name = "regex"
else:
type_name = rule.get("match", "type")
if type_name not in cls.REGISTRY:
log.warning(f'invalid match type "{type_name}" in rule at path {path}')
type_name = "invalid"
return cls.REGISTRY[type_name](path, rule)
class InvalidMatcher(Matcher):
type = "invalid"
def apply(self, data, spec, path):
pass
class MatchType(Matcher):
type = "type"
def apply(self, data, spec, path):
log.debug(f"match type {data!r} {spec!r} {path!r}")
if type(spec) in (int, float):
if type(data) not in (int, float):
raise RuleFailed(
path, f"not correct type ({nice_type(data)} is not {nice_type(spec)})"
)
def __init_subclass__(cls, **kwargs):
if cls not in Matcher.REGISTRY:
Matcher.REGISTRY[cls.type] = cls
super().__init_subclass__(**kwargs)
if data != spec:
raise RuleFailed(path, f"value {data!r} does not equal expected {spec!r}")
class MatchInclude(Matcher):
type = "include"
def apply(self, data, spec, path):
log.debug(f"match include {data!r} {spec!r} {path!r}")
if self.rule["value"] not in data:
raise RuleFailed(
path, f'value {data!r} does not contain expected value {self.rule["value"]!r}'
)
class MatchNull(Matcher):
type = "null"
def apply(self, data, spec, path):
log.debug(f"match null {data!r} {spec!r} {path!r}")
if data is not None:
raise RuleFailed(path, f"value {data!r} is not null")
class MultipleMatchers(Matcher):
type = ""
def __init__(self, path, matchers=None, combine="AND"):
super().__init__(path, matchers)
self.matchers = [Matcher.get_matcher(path, rule) for rule in matchers]
self.combine = combine
self.check_min(data, path)
self.check_max(data, path)
class MatchDecimal(Matcher):
type = "decimal"
def apply(self, data, spec, path):
log.debug(f"match decimal {data!r} {spec!r} {path!r}")
if type(data) != float:
raise RuleFailed(path, f"not correct type ({nice_type(data)} is not decimal)")
self.check_min(data, path)
self.check_max(data, path)
class MatchNumber(Matcher):
type = "number"
def apply(self, data, spec, path):
log.debug(f"match number {data!r} {spec!r} {path!r}")
if type(data) not in (int, float):
raise RuleFailed(path, f"not correct type ({nice_type(data)} is not number)")
self.check_min(data, path)
self.check_max(data, path)
class MatchEquality(Matcher):
type = "equality"
def apply(self, data, spec, path):
log.debug(f"match equality {data!r} {spec!r} {path!r}")
if data != spec:
else:
type_name = rule.get("match", "type")
if type_name not in cls.REGISTRY:
log.warning(f'invalid match type "{type_name}" in rule at path {path}')
type_name = "invalid"
return cls.REGISTRY[type_name](path, rule)
class InvalidMatcher(Matcher):
type = "invalid"
def apply(self, data, spec, path):
pass
class MatchType(Matcher):
type = "type"
def apply(self, data, spec, path):
log.debug(f"match type {data!r} {spec!r} {path!r}")
if type(spec) in (int, float):
if type(data) not in (int, float):
raise RuleFailed(
path, f"not correct type ({nice_type(data)} is not {nice_type(spec)})"
)
elif fold_type(spec) != fold_type(data):
raise RuleFailed(path, f"not correct type ({nice_type(data)} is not {nice_type(spec)})")
self.check_min(data, path)
self.check_max(data, path)
class MatchRegex(Matcher):
if type(data) not in (int, float):
raise RuleFailed(path, f"not correct type ({nice_type(data)} is not number)")
self.check_min(data, path)
self.check_max(data, path)
class MatchEquality(Matcher):
type = "equality"
def apply(self, data, spec, path):
log.debug(f"match equality {data!r} {spec!r} {path!r}")
if data != spec:
raise RuleFailed(path, f"value {data!r} does not equal expected {spec!r}")
class MatchInclude(Matcher):
type = "include"
def apply(self, data, spec, path):
log.debug(f"match include {data!r} {spec!r} {path!r}")
if self.rule["value"] not in data:
raise RuleFailed(
path, f'value {data!r} does not contain expected value {self.rule["value"]!r}'
)
class MatchNull(Matcher):
type = "null"
def apply(self, data, spec, path):
log.debug(f"match null {data!r} {spec!r} {path!r}")
if data is not None:
if re.fullmatch(self.rule["regex"], str(data)) is None:
raise RuleFailed(path, f'value {data!r} does not match regex {self.rule["regex"]}')
class MatchInteger(Matcher):
type = "integer"
def apply(self, data, spec, path):
log.debug(f"match integer {data!r} {spec!r} {path!r}")
if type(data) != int:
raise RuleFailed(path, f"not correct type ({nice_type(data)} is not integer)")
self.check_min(data, path)
self.check_max(data, path)
class MatchDecimal(Matcher):
type = "decimal"
def apply(self, data, spec, path):
log.debug(f"match decimal {data!r} {spec!r} {path!r}")
if type(data) != float:
raise RuleFailed(path, f"not correct type ({nice_type(data)} is not decimal)")
self.check_min(data, path)
self.check_max(data, path)
class MatchNumber(Matcher):
type = "number"
def apply(self, data, spec, path):
log.debug(f"match number {data!r} {spec!r} {path!r}")
if type(data) not in (int, float):
self.check_min(data, path)
self.check_max(data, path)
class MatchNumber(Matcher):
type = "number"
def apply(self, data, spec, path):
log.debug(f"match number {data!r} {spec!r} {path!r}")
if type(data) not in (int, float):
raise RuleFailed(path, f"not correct type ({nice_type(data)} is not number)")
self.check_min(data, path)
self.check_max(data, path)
class MatchEquality(Matcher):
type = "equality"
def apply(self, data, spec, path):
log.debug(f"match equality {data!r} {spec!r} {path!r}")
if data != spec:
raise RuleFailed(path, f"value {data!r} does not equal expected {spec!r}")
class MatchInclude(Matcher):
type = "include"
def apply(self, data, spec, path):
log.debug(f"match include {data!r} {spec!r} {path!r}")
if self.rule["value"] not in data:
raise RuleFailed(
path, f'value {data!r} does not contain expected value {self.rule["value"]!r}'
if self.rule["value"] not in data:
raise RuleFailed(
path, f'value {data!r} does not contain expected value {self.rule["value"]!r}'
)
class MatchNull(Matcher):
type = "null"
def apply(self, data, spec, path):
log.debug(f"match null {data!r} {spec!r} {path!r}")
if data is not None:
raise RuleFailed(path, f"value {data!r} is not null")
class MultipleMatchers(Matcher):
type = ""
def __init__(self, path, matchers=None, combine="AND"):
super().__init__(path, matchers)
self.matchers = [Matcher.get_matcher(path, rule) for rule in matchers]
self.combine = combine
def apply(self, data, spec, path):
log.debug(f"MultipleMatchers.__call__ {data!r} {spec!r} {path!r}")
for matcher in self.matchers:
log.debug(f"... matching {matcher}")
try:
matcher.apply(data, spec, path)
except RuleFailed:
if self.combine == "AND":
raise