55from 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-
138def 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
88121def 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