Skip to content

Commit b522281

Browse files
authored
Fix: correct the path of required (#83)
* Fix: correct the path of required * Add comment * Fix: linter check
1 parent f576f7a commit b522281

File tree

2 files changed

+148
-3
lines changed

2 files changed

+148
-3
lines changed

src/rpdk/guard_rail/core/stateful.py

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,10 +184,17 @@ def _add_item(
184184
"""Appends values to existing/new meta diff values"""
185185
if result_key not in schema_meta_diff:
186186
schema_meta_diff[result_key] = {}
187+
187188
if change_key in schema_meta_diff[result_key]:
188-
schema_meta_diff[result_key][change_key].append(result_value)
189+
if isinstance(result_value, (list, tuple)):
190+
schema_meta_diff[result_key][change_key].extend(result_value)
191+
else:
192+
schema_meta_diff[result_key][change_key].append(result_value)
189193
else:
190-
schema_meta_diff[result_key][change_key] = [result_value]
194+
if isinstance(result_value, (list, tuple)):
195+
schema_meta_diff[result_key][change_key] = list(result_value)
196+
else:
197+
schema_meta_diff[result_key][change_key] = [result_value]
191198

192199

193200
def _traverse_nested_properties(
@@ -330,11 +337,25 @@ def __translate_dict_diff(diffkey, schema_meta_diff, diff_value):
330337
schema_meta_diff, diffkey, _get_path(path_list), value
331338
)
332339
if _is_json_construct(path_list):
340+
# If the last element in path_list is "required":
341+
# - For list/tuple values: Creates a list of paths by combining each value with the parent path
342+
# - For single values: Creates a single path by combining the value with the parent path
343+
# Otherwise:
344+
# - Returns the parent path without the last element
345+
if path_list[-1] == "required":
346+
if isinstance(value, (list, tuple)):
347+
path_list_required = [
348+
_get_path(path_list[:-1] + [v]) for v in value
349+
]
350+
else:
351+
path_list_required = _get_path(path_list[:-1] + [value])
352+
else:
353+
path_list_required = _get_path(path_list[:-1])
333354
_add_item(
334355
schema_meta_diff,
335356
path_list[-1],
336357
diffkey,
337-
_get_path(path_list[:-1]),
358+
path_list_required,
338359
)
339360
if _is_cfn_leaf_construct(path_list):
340361
_add_item(

tests/unit/core/test_stateful.py

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# pylint: disable=C0301
2+
# pylint: disable=C0302
23
"""
34
Unit test for stateful.py
45
"""
@@ -965,3 +966,126 @@ def test_schema_diff_complex_json_semantics_with_combiners_mutations(
965966
"Schemas with combiners are not yet supported for stateful evaluation"
966967
== str(e)
967968
)
969+
970+
971+
@pytest.mark.parametrize(
972+
"schema_variant1, schema_variant2, expected_diff, expected_diff_negative",
973+
[
974+
(
975+
{
976+
"definitions": {
977+
"A": {
978+
"description": "Information about the automation configuration in numeric questions.",
979+
"type": "object",
980+
"additionalProperties": False,
981+
"properties": {
982+
"X": {
983+
"description": "",
984+
"$ref": "#/definitions/B",
985+
}
986+
},
987+
},
988+
"B": {
989+
"description": "",
990+
"type": "object",
991+
"additionalProperties": False,
992+
"properties": {
993+
"Y": {
994+
"description": "The type of the answer sourcr",
995+
"type": "string",
996+
"enum": ["CONTACT_LENS_DATA", "GEN_AI"],
997+
},
998+
"Z": {
999+
"description": "",
1000+
},
1001+
},
1002+
"required": ["Y", "Z"],
1003+
},
1004+
},
1005+
"properties": {
1006+
"Items": {
1007+
"description": "Items that are part of the evaluation form.",
1008+
"type": "array",
1009+
"insertionOrder": True,
1010+
"minItems": 1,
1011+
"maxItems": 200,
1012+
"items": {"$ref": "#/definitions/A"},
1013+
}
1014+
},
1015+
},
1016+
{
1017+
"definitions": {
1018+
"A": {
1019+
"description": "Information about the automation configuration in numeric questions.",
1020+
"type": "object",
1021+
"additionalProperties": False,
1022+
"properties": {
1023+
"X": {
1024+
"description": "",
1025+
}
1026+
},
1027+
},
1028+
},
1029+
"properties": {
1030+
"Items": {
1031+
"description": "Items that are part of the evaluation form.",
1032+
"type": "array",
1033+
"insertionOrder": True,
1034+
"minItems": 1,
1035+
"maxItems": 200,
1036+
"items": {"$ref": "#/definitions/A"},
1037+
}
1038+
},
1039+
},
1040+
{
1041+
"type": {"added": ["/properties/Items/*/X"]},
1042+
"additionalProperties": {"added": ["/properties/Items/*/X"]},
1043+
"properties": {
1044+
"added": [
1045+
"/properties/Items/*/X/properties",
1046+
"/properties/Items/*/X/properties/Y",
1047+
"/properties/Items/*/X/properties/Z",
1048+
"/properties/Items/*/X/properties/Z/description",
1049+
]
1050+
},
1051+
"required": {
1052+
"added": [
1053+
"/properties/Items/*/X/Y",
1054+
"/properties/Items/*/X/Z",
1055+
]
1056+
},
1057+
},
1058+
{
1059+
"type": {"removed": ["/properties/Items/*/X"]},
1060+
"additionalProperties": {"removed": ["/properties/Items/*/X"]},
1061+
"properties": {
1062+
"removed": [
1063+
"/properties/Items/*/X/properties",
1064+
"/properties/Items/*/X/properties/Y",
1065+
"/properties/Items/*/X/properties/Z",
1066+
"/properties/Items/*/X/properties/Z/description",
1067+
]
1068+
},
1069+
"required": {
1070+
"removed": [
1071+
"/properties/Items/*/X/Y",
1072+
"/properties/Items/*/X/Z",
1073+
]
1074+
},
1075+
},
1076+
)
1077+
],
1078+
)
1079+
def test_schema_diff_show_correct_required_source(
1080+
schema_variant1, schema_variant2, expected_diff, expected_diff_negative
1081+
):
1082+
"""
1083+
1084+
Args:
1085+
schema_variant1:
1086+
schema_variant2:
1087+
expected_diff:
1088+
expected_diff_negative:
1089+
"""
1090+
assert expected_diff == schema_diff(schema_variant2, schema_variant1)
1091+
assert expected_diff_negative == schema_diff(schema_variant1, schema_variant2)

0 commit comments

Comments
 (0)