Skip to content

Commit 9d2d418

Browse files
committed
add: seventh step, processing nested dictionaries
1 parent 0aa429e commit 9d2d418

File tree

1 file changed

+75
-38
lines changed

1 file changed

+75
-38
lines changed

gendiff/gendiff.py

Lines changed: 75 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,6 @@
55
from gendiff.cli import parse_args
66

77

8-
def main() -> None:
9-
args = parse_args()
10-
print(generate_diff(args.first_file, args.second_file))
11-
12-
138
def read_file(path: str):
149
try:
1510
if path.endswith('.json'):
@@ -29,36 +24,31 @@ def read_file(path: str):
2924
return None
3025

3126

32-
def get_list_of_dict_with_sign(data1, data2) -> list:
33-
result = [
34-
{'key': key, 'sign': ' ', 'value': value}
35-
if (key in data2) and (value == data2[key])
36-
else {'key': key, 'sign': '-', 'value': value}
37-
for key, value in data1.items()
38-
]
39-
result.extend([
40-
{'key': key, 'sign': '+', 'value': value}
41-
for key, value in data2.items()
42-
if (key not in data1) or value != data1[key]
43-
])
44-
return result
45-
46-
47-
def sort_list(items: list):
48-
def sort_by_rule(item: dict) -> tuple:
49-
"""The sign -> digit for correctly sort items with the same key."""
50-
sign_order = {'-': 0, '+': 1, ' ': 2}
51-
return (item['key'], sign_order[item['sign']])
52-
items.sort(key=sort_by_rule)
53-
return items
27+
def make_str_from_dict(items: dict, enclos=0) -> str:
28+
indent = ' ' * enclos
29+
list_of_str = ['{']
30+
for key, value in items.items():
31+
if not isinstance(key, str):
32+
key = json.dumps(key)
33+
34+
if isinstance(value, dict):
35+
value = make_str_from_dict(value, enclos + 1)
36+
37+
if not isinstance(value, str):
38+
value = json.dumps(value)
39+
40+
list_of_str.append(f"{indent} {key}: {value}")
41+
list_of_str.append(f"{indent}}}")
42+
return '\n'.join(list_of_str)
5443

5544

56-
def make_str_from_list(items: list) -> str:
45+
def make_str_from_list(items: list, enclos=0) -> str:
5746
"""
5847
Type checking for the output of strings without quotes,
5948
and for the correct output of True, False in the form of true, false.
6049
Doesn't matter for .yaml.
6150
"""
51+
indent = ' ' * enclos
6252
list_of_str = ['{']
6353
for item in items:
6454
sign = item['sign']
@@ -70,24 +60,71 @@ def make_str_from_list(items: list) -> str:
7060

7161
if isinstance(item['value'], str):
7262
value = item['value']
63+
elif isinstance(item['value'], list):
64+
value = make_str_from_list(item['value'], enclos + 1)
65+
elif isinstance(item['value'], dict):
66+
value = make_str_from_dict(item['value'], enclos + 1)
7367
else:
7468
value = json.dumps(item['value'])
7569

76-
list_of_str.append(f" {sign} {key}: {value}")
77-
list_of_str.append('}')
70+
list_of_str.append(f"{indent} {sign} {key}: {value}")
71+
list_of_str.append(f"{indent}}}")
7872
return '\n'.join(list_of_str)
7973

8074

81-
# def check_the_nesting(list_of_dict: list) -> list:
82-
# for item in list_of_dict:
83-
# value = item['value']
84-
# if isinstance(value, dict):
85-
# get_list_of_dict_with_sign(value)
75+
def sort_list(items: list):
76+
def sort_by_rule(item: dict) -> tuple:
77+
"""The sign -> digit for correctly sort items with the same key."""
78+
sign_order = {'-': 0, '+': 1, ' ': 2}
79+
return (item['key'], sign_order[item['sign']])
80+
items.sort(key=sort_by_rule)
81+
return items
82+
83+
84+
def get_list_of_dict(data1, data2) -> list:
85+
if data1 == data2:
86+
return data1
87+
result = [
88+
{
89+
'key': key,
90+
'sign': ' ',
91+
'value': get_list_of_dict(value, data2[key])
92+
}
93+
if key in data2 and (
94+
(value == data2[key]) or
95+
(value != data2[key]) and
96+
(isinstance(value, dict) and isinstance(data2[key], dict))
97+
)
98+
else {
99+
'key': key,
100+
'sign': '-',
101+
'value': value
102+
}
103+
for key, value in data1.items()
104+
]
105+
result.extend([
106+
{
107+
'key': key,
108+
'sign': '+',
109+
'value': value
110+
}
111+
for key, value in data2.items()
112+
if (
113+
(key not in data1) or
114+
(key in data1 and value != data1[key]) and
115+
(not isinstance(value, dict) or not isinstance(data2[key], dict))
116+
)
117+
])
118+
return sort_list(result)
86119

87120

88121
def generate_diff(path1, path2) -> str:
89122
dict_data1 = read_file(path1)
90123
dict_data2 = read_file(path2)
91-
list_of_dict = get_list_of_dict_with_sign(dict_data1, dict_data2)
92-
sorted_list = sort_list(list_of_dict)
93-
return make_str_from_list(sorted_list)
124+
sorted_list_of_dict = get_list_of_dict(dict_data1, dict_data2)
125+
return make_str_from_list(sorted_list_of_dict)
126+
127+
128+
def main() -> None:
129+
args = parse_args()
130+
print(generate_diff(args.first_file, args.second_file))

0 commit comments

Comments
 (0)