Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def apply_rules_dict(self, data, spec, path):
log.debug(f"apply_rules_dict data={data!r} spec={spec!r} path={format_path(path)}")
if fold_type(data) is not dict:
return self.result.fail(
f"{self.interaction_name} element is not an object (is {nice_type(data)})", path
)
for k in spec:
p = path + [k]
if k not in data:
# we always flag a failure if a given key is not in the response
return self.result.fail(f"{self.interaction_name} element {k!r} is missing", path)
if not self.apply_rules(data[k], spec[k], p):
return False
return True
def compare_list(self, data, path, spec):
if fold_type(data) is not list:
return self.result.fail(
f"{self.interaction_name} element is not an array (is {nice_type(data)})", path
)
if len(data) != len(spec):
return self.result.fail(
f"{self.interaction_name} array is incorrect length (is {len(data)} elements)", path
)
for i, (data_elem, spec_elem) in enumerate(zip(data, spec)):
p = path + [i]
if not self.compare(data_elem, spec_elem, p):
return self.result.fail(
f"{self.interaction_name} element {i} ({nice_type(data_elem)}) "
f"does not match spec ({nice_type(spec_elem)})",
path,
)
return True
def compare(self, data, spec, path):
log.debug(f"compare data={data!r} spec={spec!r} path={format_path(path)}")
if fold_type(spec) is list:
return self.compare_list(data, path, spec)
if fold_type(spec) is dict:
return self.compare_dict(data, spec, path)
if data != spec:
return self.result.fail(f"Element mismatch {data!r} is not expected {spec!r}", path)
return True
def apply_rules_array(self, data, spec, path):
log.debug(f"apply_rules_array data={data!r} spec={spec!r} path={format_path(path)}")
if fold_type(data) is not list:
return self.result.fail(
f"{self.interaction_name} element is not an array (is {nice_type(data)})", path
)
if not data and not spec:
# both arrays are empty, there's no further rules to apply
return True
if not spec and data:
return self.result.fail(
f"{self.interaction_name} spec requires empty array but data has contents", path
)
if spec and not data:
return self.result.fail(
f"{self.interaction_name} spec requires data in array but data is empty", path
weighted_rule = self.find_rule(path)
log.debug(f"... rule lookup got {weighted_rule}")
if weighted_rule:
try:
weighted_rule.rule.apply(data, spec, path)
except RuleFailed as e:
log.debug(f"... failed: {e}")
return self.result.fail(str(e), path)
log.debug("... passed")
# we passed the matchingRule but we also need to check the contents of arrays/dicts
if fold_type(spec) is list:
r = self.apply_rules_array(data, spec, path)
log.debug(f"apply_rules {format_path(path)} success={r!r}")
return r
elif fold_type(spec) is dict:
r = self.apply_rules_dict(data, spec, path)
log.debug(f"apply_rules {format_path(path)} success={r!r}")
return r
elif not weighted_rule:
if path[0] in ("header", "headers"):
log.debug("... falling back on header matching")
return self.compare_header(data, spec, path)
else:
# in the absence of a rule, and we're at a leaf, we fall back on equality
log.debug("... falling back on equality matching {data} vs {spec}")
if data != spec:
return self.result.fail(
f"Element mismatch {data!r} is not expected {spec!r}", path
)
return True
def compare(self, data, spec, path):
log.debug(f"compare data={data!r} spec={spec!r} path={format_path(path)}")
if fold_type(spec) is list:
return self.compare_list(data, path, spec)
if fold_type(spec) is dict:
return self.compare_dict(data, spec, path)
if data != spec:
return self.result.fail(f"Element mismatch {data!r} is not expected {spec!r}", path)
return True
def apply_rules(self, data, spec, path):
# given some actual data and a pact spec at a certain path, check any rules for that path
log.debug(f"apply_rules data={data!r} spec={spec!r} path={format_path(path)}")
weighted_rule = self.find_rule(path)
log.debug(f"... rule lookup got {weighted_rule}")
if weighted_rule:
try:
weighted_rule.rule.apply(data, spec, path)
except RuleFailed as e:
log.debug(f"... failed: {e}")
return self.result.fail(str(e), path)
log.debug("... passed")
# we passed the matchingRule but we also need to check the contents of arrays/dicts
if fold_type(spec) is list:
r = self.apply_rules_array(data, spec, path)
log.debug(f"apply_rules {format_path(path)} success={r!r}")
return r
elif fold_type(spec) is dict:
r = self.apply_rules_dict(data, spec, path)
log.debug(f"apply_rules {format_path(path)} success={r!r}")
return r
elif not weighted_rule:
if path[0] in ("header", "headers"):
log.debug("... falling back on header matching")
return self.compare_header(data, spec, path)
else:
# in the absence of a rule, and we're at a leaf, we fall back on equality
log.debug("... falling back on equality matching {data} vs {spec}")
if data != spec:
return self.result.fail(