cfn-check 0.5.0__py3-none-any.whl → 0.6.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of cfn-check might be problematic. Click here for more details.

@@ -26,6 +26,7 @@ class Renderer:
26
26
  self._mappings = CommentedMap()
27
27
  self._parameters_with_defaults: dict[str, str | int | float | bool | None] = {}
28
28
  self._selected_mappings = CommentedMap()
29
+ self._conditions = CommentedMap()
29
30
  self._references: dict[str, str] = {}
30
31
  self._resources: dict[str, YamlObject] = CommentedMap()
31
32
  self._attributes: dict[str, str] = {}
@@ -39,7 +40,13 @@ class Renderer:
39
40
  '!Base64': self._resolve_base64,
40
41
  '!Split': self._resolve_split,
41
42
  '!Select': self._resolve_select,
42
- '!ToJsonString': self._resolve_to_json_string,
43
+ '!ToJsonString': self._resolve_tree_to_json,
44
+ '!Equals': self._resolve_equals,
45
+ '!If': self._resolve_if,
46
+ '!Condition': self._resolve_condition,
47
+ '!And': self._resolve_and,
48
+ '!Not': self._resolve_not,
49
+ '!Or': self._resolve_or
43
50
  }
44
51
 
45
52
  def render(
@@ -79,13 +86,13 @@ class Renderer:
79
86
  self._selected_mappings = mappings
80
87
 
81
88
  self._resources = template.get('Resources', CommentedMap())
89
+ self._conditions = template.get('Conditions', CommentedMap())
82
90
 
83
91
  return self._resolve_tree(template)
84
92
 
85
93
  def _resolve_tree(self, root: YamlObject):
86
94
  self.items.clear()
87
95
  self.items.append((None, None, root))
88
- self.items.append((None, None, root))
89
96
 
90
97
  while self.items:
91
98
  parent, accessor, node = self.items.pop()
@@ -98,9 +105,8 @@ class Renderer:
98
105
  parent[accessor] = resolved
99
106
 
100
107
  elif isinstance(node, CommentedMap):
101
- if isinstance(node.tag, Tag) and node.tag.value is not None and parent and (
102
- resolved_node := self._resolve_tagged(root, node)
103
- ):
108
+ if isinstance(node.tag, Tag) and node.tag.value is not None and parent:
109
+ resolved_node = self._resolve_tagged(root, node)
104
110
  parent[accessor] = resolved_node
105
111
 
106
112
  elif isinstance(node.tag, Tag) and node.tag.value is not None:
@@ -117,13 +123,13 @@ class Renderer:
117
123
 
118
124
  elif isinstance(node, CommentedSeq):
119
125
 
120
- if isinstance(node.tag, Tag) and node.tag.value is not None and parent and (
121
- resolved_node := self._resolve_tagged(root, node)
122
- ):
126
+ if isinstance(node.tag, Tag) and node.tag.value is not None and parent:
127
+ resolved_node = self._resolve_tagged(root, node)
123
128
  parent[accessor] = resolved_node
124
129
 
125
130
  elif isinstance(node.tag, Tag) and node.tag.value is not None:
126
131
  node = self._resolve_tagged(root, node)
132
+
127
133
  for idx, val in enumerate(reversed(node)):
128
134
  self.items.append((node, idx, val))
129
135
 
@@ -328,7 +334,7 @@ class Renderer:
328
334
  resolved = self._resolve_subtree(root, subselction)
329
335
 
330
336
  if not isinstance(resolved, CommentedSeq):
331
- return resolved
337
+ return source
332
338
 
333
339
  return delimiter.join([
334
340
  str(self._resolve_tagged(
@@ -453,7 +459,195 @@ class Renderer:
453
459
 
454
460
  return target[index]
455
461
 
456
- def _resolve_to_json_string(
462
+ def _resolve_equals(
463
+ self,
464
+ root: CommentedMap,
465
+ source: CommentedSeq | CommentedMap | TaggedScalar,
466
+ ):
467
+ if isinstance(
468
+ source,
469
+ (CommentedMap, TaggedScalar),
470
+ ) or len(source) != 2:
471
+ return source
472
+
473
+ item_a = source[0]
474
+ if isinstance(
475
+ item_a,
476
+ (CommentedMap, CommentedSeq, TaggedScalar),
477
+ ):
478
+ item_a = self._resolve_subtree(root, item_a)
479
+
480
+ item_b = source[1]
481
+ if isinstance(
482
+ item_b,
483
+ (CommentedMap, CommentedSeq, TaggedScalar),
484
+ ):
485
+ item_b = self._resolve_subtree(root, item_b)
486
+
487
+ return item_a == item_b
488
+
489
+ def _resolve_if(
490
+ self,
491
+ root: CommentedMap,
492
+ source: CommentedSeq | CommentedMap | TaggedScalar,
493
+ ):
494
+ if isinstance(
495
+ source,
496
+ (CommentedMap, TaggedScalar),
497
+ ) or len(source) != 3:
498
+ return source
499
+
500
+ condition_key = source[0]
501
+ if isinstance(
502
+ condition_key,
503
+ (CommentedMap, CommentedSeq, TaggedScalar),
504
+ ):
505
+ condition_key = self._resolve_subtree(root, condition_key)
506
+
507
+ true_result = source[1]
508
+ if isinstance(
509
+ true_result,
510
+ (CommentedMap, CommentedSeq, TaggedScalar),
511
+ ):
512
+ true_result = self._resolve_subtree(root, true_result)
513
+
514
+ false_result = source[2]
515
+ if isinstance(
516
+ true_result,
517
+ (CommentedMap, CommentedSeq, TaggedScalar),
518
+ ):
519
+ false_result = self._resolve_subtree(root, false_result)
520
+
521
+ if (
522
+ condition := self._conditions.get(condition_key)
523
+ ) and isinstance(
524
+ condition,
525
+ (CommentedMap, CommentedSeq, TaggedScalar)
526
+ ) and (
527
+ result := self._resolve_subtree(root, condition)
528
+ ) and isinstance(
529
+ result,
530
+ bool,
531
+ ):
532
+
533
+ return true_result if result else False
534
+
535
+ elif (
536
+ condition := self._conditions.get(condition_key)
537
+ ) and isinstance(
538
+ condition,
539
+ bool,
540
+ ):
541
+ return true_result if condition else False
542
+
543
+ return source
544
+
545
+ def _resolve_condition(
546
+ self,
547
+ root: CommentedMap,
548
+ source: CommentedSeq | CommentedMap | TaggedScalar,
549
+ ):
550
+ if isinstance(
551
+ source,
552
+ (CommentedMap, CommentedSeq),
553
+ ):
554
+ return source
555
+
556
+ if (
557
+ condition := self._conditions.get(source.value)
558
+ ) and isinstance(
559
+ condition,
560
+ (CommentedMap, CommentedSeq, TaggedScalar)
561
+ ) and (
562
+ result := self._resolve_subtree(root, condition)
563
+ ) and isinstance(
564
+ result,
565
+ bool,
566
+ ):
567
+ return result
568
+
569
+ elif (
570
+ condition := self._conditions.get(source.value)
571
+ ) and isinstance(
572
+ condition,
573
+ bool,
574
+ ):
575
+ return condition
576
+
577
+ return source
578
+
579
+ def _resolve_and(
580
+ self,
581
+ root: CommentedMap,
582
+ source: CommentedSeq | CommentedMap | TaggedScalar,
583
+ ):
584
+ if isinstance(
585
+ source,
586
+ (CommentedMap, TaggedScalar),
587
+ ):
588
+ return source
589
+
590
+ resolved = self._resolve_subtree(root, CommentedSeq([
591
+ item for item in source
592
+ ]))
593
+ if not isinstance(resolved, CommentedSeq):
594
+ return source
595
+
596
+
597
+ for node in resolved:
598
+ if not isinstance(node, bool):
599
+ return source
600
+
601
+ return all(resolved)
602
+
603
+ def _resolve_not(
604
+ self,
605
+ root: CommentedMap,
606
+ source: CommentedSeq | CommentedMap | TaggedScalar,
607
+ ):
608
+ if isinstance(
609
+ source,
610
+ (CommentedMap, TaggedScalar),
611
+ ):
612
+ return source
613
+
614
+ resolved = self._resolve_subtree(root, CommentedSeq([
615
+ item for item in source
616
+ ]))
617
+ if not isinstance(resolved, CommentedSeq):
618
+ return source
619
+
620
+ for node in resolved:
621
+ if not isinstance(node, bool):
622
+ return source
623
+
624
+ return not all(resolved)
625
+
626
+ def _resolve_or(
627
+ self,
628
+ root: CommentedMap,
629
+ source: CommentedSeq | CommentedMap | TaggedScalar,
630
+ ):
631
+ if isinstance(
632
+ source,
633
+ (CommentedMap, TaggedScalar),
634
+ ):
635
+ return source
636
+
637
+ resolved = self._resolve_subtree(root, CommentedSeq([
638
+ item for item in source
639
+ ]))
640
+ if not isinstance(resolved, CommentedSeq):
641
+ return source
642
+
643
+
644
+ for node in resolved:
645
+ if not isinstance(node, bool):
646
+ return source
647
+
648
+ return any(resolved)
649
+
650
+ def _resolve_tree_to_json(
457
651
  self,
458
652
  root: CommentedMap,
459
653
  source: CommentedSeq | CommentedMap | TaggedScalar,
@@ -470,6 +664,11 @@ class Renderer:
470
664
  ):
471
665
  parent[accessor] = resolved
472
666
 
667
+ elif (
668
+ resolved := self._resolve_tagged(root, node)
669
+ ):
670
+ source = resolved
671
+
473
672
  elif isinstance(node, CommentedMap):
474
673
  if isinstance(node.tag, Tag) and node.tag.value is not None and parent and (
475
674
  resolved_node := self._resolve_tagged(root, node)
@@ -518,7 +717,7 @@ class Renderer:
518
717
  - CommentedMap/CommentedSeq are traversed.
519
718
  """
520
719
  stack: list[tuple[CommentedMap | CommentedSeq | None, Any | None, Any]] = [(None, None, source)]
521
-
720
+
522
721
  while stack:
523
722
  parent, accessor, node = stack.pop()
524
723
  if isinstance(node, TaggedScalar):
@@ -528,10 +727,14 @@ class Renderer:
528
727
  ):
529
728
  parent[accessor] = resolved
530
729
 
531
- elif isinstance(node, CommentedMap):
532
- if isinstance(node.tag, Tag) and node.tag.value is not None and parent and (
533
- resolved_node := self._resolve_tagged(root, node)
730
+ elif (
731
+ resolved := self._resolve_tagged(root, node)
534
732
  ):
733
+ source = resolved
734
+
735
+ elif isinstance(node, CommentedMap):
736
+ if isinstance(node.tag, Tag) and node.tag.value is not None and parent:
737
+ resolved_node = self._resolve_tagged(root, node)
535
738
  parent[accessor] = resolved_node
536
739
 
537
740
  elif isinstance(node.tag, Tag) and node.tag.value is not None:
@@ -547,9 +750,8 @@ class Renderer:
547
750
  stack.append((node, k, node[k]))
548
751
 
549
752
  elif isinstance(node, CommentedSeq):
550
- if isinstance(node.tag, Tag) and node.tag.value is not None and parent and (
551
- resolved_node := self._resolve_tagged(root, node)
552
- ):
753
+ if isinstance(node.tag, Tag) and node.tag.value is not None and parent:
754
+ resolved_node = self._resolve_tagged(root, node)
553
755
  parent[accessor] = resolved_node
554
756
 
555
757
  elif isinstance(node.tag, Tag) and node.tag.value is not None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cfn-check
3
- Version: 0.5.0
3
+ Version: 0.6.0
4
4
  Summary: Validate Cloud Formation
5
5
  Author-email: Ada Lundhe <adalundhe@lundhe.audio>
6
6
  License: MIT License
@@ -19,7 +19,7 @@ cfn_check/evaluation/parsing/token_type.py,sha256=E5AVBerinBszMLjjc7ejwSSWEc0p0J
19
19
  cfn_check/logging/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
20
  cfn_check/logging/models.py,sha256=-tBaK6p8mJ0cO8h2keEJ-VmtFX_VW4XzwAw2PtqbkF0,490
21
21
  cfn_check/rendering/__init__.py,sha256=atcbddYun4YHyY7bVGA9CgEYzzXpYzvkx9_Kg-gnD5w,42
22
- cfn_check/rendering/renderer.py,sha256=mPLyXyv0yUsCZnKuLZg8yDN1NQlFivX-P8_bwhQqzXI,25903
22
+ cfn_check/rendering/renderer.py,sha256=xbSPfjX6w-xcGULLJ_3m3k3PrnDNWdaB418OaVT-J8A,31389
23
23
  cfn_check/rendering/utils.py,sha256=MNaKePylbJ9Bs4kjuoV0PpCmPJYttPXXvKQILemCrUI,489
24
24
  cfn_check/rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
25
  cfn_check/rules/rule.py,sha256=_cKNQ5ciJgPj-exmtBUz31cU2lxWYxw2n2NWIlhYc3s,635
@@ -27,13 +27,13 @@ cfn_check/shared/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,
27
27
  cfn_check/shared/types.py,sha256=-om3DyZsjK_tJd-I8SITkoE55W0nB2WA3LOc87Cs7xI,414
28
28
  cfn_check/validation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
29
  cfn_check/validation/validator.py,sha256=Z6S6T_4yQW1IUa5Kv3ohR9U8NDrhTvBadW2FEM8TRL8,1478
30
- cfn_check-0.5.0.dist-info/licenses/LICENSE,sha256=EbCpGNzOkyQ53ig7J2Iwgmy4Og0dgHe8COo3WylhIKk,1069
30
+ cfn_check-0.6.0.dist-info/licenses/LICENSE,sha256=EbCpGNzOkyQ53ig7J2Iwgmy4Og0dgHe8COo3WylhIKk,1069
31
31
  example/multitag.py,sha256=QQfcRERGEDgTUCGqWRqRbXHrLwSX4jEOFq8ED4NJnz8,636
32
32
  example/pydantic_rules.py,sha256=6NFtDiaqmnYWt6oZIWB7AO_v5LJoZVOGXrmEe2_J_rI,4162
33
33
  example/renderer_test.py,sha256=XG5PVTSHztYXHrBw4bpwVuuYt1JNZdtLGJ-DZ9wPjFM,741
34
34
  example/rules.py,sha256=mWHB0DK283lb0CeSHgnyO5qiVTJJpybuwWXb4Yoa3zQ,3148
35
- cfn_check-0.5.0.dist-info/METADATA,sha256=KJXT9Yc29NfwClW04f0TcQe1gI7iu82mNV_MpLb2aRg,20459
36
- cfn_check-0.5.0.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
37
- cfn_check-0.5.0.dist-info/entry_points.txt,sha256=B4lCHoDHmwisABxKgRLShwqqFv7QwwDAFXoAChOnkwg,53
38
- cfn_check-0.5.0.dist-info/top_level.txt,sha256=hUn9Ya50yY1fpgWxEhG5iMgfMDDVX7qWQnM1xrgZnhM,18
39
- cfn_check-0.5.0.dist-info/RECORD,,
35
+ cfn_check-0.6.0.dist-info/METADATA,sha256=YhkiamHlnRXbS6bVDUiTiWPHU4BgEwGqVKgHoCLBN28,20459
36
+ cfn_check-0.6.0.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
37
+ cfn_check-0.6.0.dist-info/entry_points.txt,sha256=B4lCHoDHmwisABxKgRLShwqqFv7QwwDAFXoAChOnkwg,53
38
+ cfn_check-0.6.0.dist-info/top_level.txt,sha256=hUn9Ya50yY1fpgWxEhG5iMgfMDDVX7qWQnM1xrgZnhM,18
39
+ cfn_check-0.6.0.dist-info/RECORD,,