Skip to content

Commit

Permalink
Fix resolver logic for better context logic (#3915)
Browse files Browse the repository at this point in the history
  • Loading branch information
kddejong authored Jan 15, 2025
1 parent 84bf681 commit e963902
Show file tree
Hide file tree
Showing 2 changed files with 274 additions and 53 deletions.
44 changes: 31 additions & 13 deletions src/cfnlint/jsonschema/_resolvers_cfn.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import json
from collections import deque
from copy import deepcopy
from typing import Any, Iterator

import regex as re
Expand Down Expand Up @@ -243,9 +244,9 @@ def find_in_map(validator: Validator, instance: Any) -> ResolutionResult:
):
yield (
value,
validator.evolve(
context=validator.context.evolve(
path=validator.context.path.evolve(
second_v.evolve(
context=second_v.context.evolve(
path=second_v.context.path.evolve(
value_path=deque(
[
"Mappings",
Expand Down Expand Up @@ -282,24 +283,28 @@ def get_azs(validator: Validator, instance: Any) -> ResolutionResult:
yield AVAILABILITY_ZONES.get(instance), v, None


def _join_expansion(validator: Validator, instances: Any) -> Iterator[Any]:
def _join_expansion(
validator: Validator, instances: Any
) -> Iterator[tuple[Any, Validator]]:
if len(instances) == 0:
return

if len(instances) == 1:
for value, _, _ in validator.resolve_value(instances[0]):
for value, instance_validator, _ in validator.resolve_value(instances[0]):
if not isinstance(value, (str, int, float, bool)):
raise ValueError(f"Incorrect value type for {value!r}")
yield [value]
yield [value], instance_validator
return

for value, instance_validator, errs in validator.resolve_value(instances[0]):
if errs:
continue
if not isinstance(value, (str, int, float, bool)):
raise ValueError(f"Incorrect value type for {value!r}")
for values in _join_expansion(instance_validator, instances[1:]):
yield [value] + values
for values, expansion_validator in _join_expansion(
instance_validator, instances[1:]
):
yield [value] + values, expansion_validator


def join(validator: Validator, instance: Any) -> ResolutionResult:
Expand All @@ -312,12 +317,21 @@ def join(validator: Validator, instance: Any) -> ResolutionResult:
for delimiter, delimiter_v, _ in validator.resolve_value(instance[0]):
if not delimiter_v.is_type(delimiter, "string"):
continue
for values, values_v, _ in validator.resolve_value(instance[1]):
for values, values_v, _ in delimiter_v.resolve_value(instance[1]):
if not values_v.is_type(values, "array"):
continue
try:
for value in _join_expansion(values_v, values):
yield delimiter.join([str(v) for v in value]), values_v, None
for value, expansion_validator in _join_expansion(values_v, values):
# reset the value path because we could get a Ref value_path
yield delimiter.join(
[str(v) for v in value]
), expansion_validator.evolve(
context=expansion_validator.context.evolve(
path=expansion_validator.context.path.evolve(
value_path=deque([])
)
)
), None
except (ValueError, TypeError):
return

Expand Down Expand Up @@ -417,7 +431,7 @@ def sub(validator: Validator, instance: Any) -> ResolutionResult:
return

string = instance[0]
parameters = instance[1]
parameters = deepcopy(instance[1])
if not validator.is_type(string, "string"):
return
if not validator.is_type(parameters, "object"):
Expand All @@ -438,7 +452,11 @@ def sub(validator: Validator, instance: Any) -> ResolutionResult:
ref_values=resolved_parameters,
)
)
yield from _sub_string(resolved_validator, string)
for sub_string, sub_validator, _ in _sub_string(resolved_validator, string):
for key in instance[1].keys():
sub_validator.context.ref_values.pop(key, None)

yield sub_string, sub_validator, None

return

Expand Down
Loading

0 comments on commit e963902

Please sign in to comment.