Skip to content

Commit

Permalink
Almost finish
Browse files Browse the repository at this point in the history
  • Loading branch information
JduMoment committed Jan 19, 2024
1 parent 648258d commit 344381e
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 169 deletions.
1 change: 0 additions & 1 deletion diff_list.py

This file was deleted.

8 changes: 4 additions & 4 deletions gendiff/construct_diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ def construct_diff(data_1: Dict, data_2: Dict) -> List:
node_type=SAME,
))
elif isinstance(value_data_1, dict) and isinstance(value_data_2, dict):
construct = build_diff(value_data_1, value_data_2)
children = construct_diff(value_data_1, value_data_2)
diff.append(dict(
key=key,
value=construct,
children=children,
node_type=NESTED,
))
else:
Expand All @@ -50,6 +50,6 @@ def construct_diff(data_1: Dict, data_2: Dict) -> List:

def build_diff(data_1, data_2):
return dict(
type='root',
node_type='root',
children=construct_diff(data_1, data_2),
)
)
15 changes: 7 additions & 8 deletions gendiff/generate_diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@
from gendiff.generate_json_file import python_to_json


def generate_diff(file_path_1, file_path_2, format_name):
def generate_diff(file_path_1, file_path_2, format_name='stylish'):
file1, file2 = transform_to_dict(file_path_1, file_path_2)
diff = build_diff(file1, file2)
return diff
# if format_name == 'stylish':
# return generate_stylish_lines(diff)
# elif format_name == 'plain':
# return generate_plain_lines(diff)
# elif format_name == 'json':
# return python_to_json(diff)
if format_name == 'stylish':
return generate_stylish_lines(diff)
elif format_name == 'plain':
return generate_plain_lines(diff)
elif format_name == 'json':
return python_to_json(diff)
57 changes: 29 additions & 28 deletions gendiff/generate_plain_lines.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,33 @@ def processing_value(value):
return f"'{value}'"


def generate_plain_lines(diff_list, parent=''):
if diff_list is None or len(diff_list) == 0:
return ''
lines = []
for every_dict in diff_list:
key = every_dict['key']
value = every_dict.get('value')
changes = every_dict['changes']
if changes == 'CHANGED':
if isinstance(value, list):
result = generate_plain_lines(value, parent + f"{key}.")
def generate_plain_lines(diff_tree, parent=''):
key = diff_tree.get('key')
value = diff_tree.get('value')
node_type = diff_tree.get('node_type')
if node_type == 'root':
children = diff_tree['children']
lines = []
for child in children:
result = generate_plain_lines(child)
lines.append(result)
return '\n'.join(lines)
elif node_type == 'NESTED':
children = diff_tree['children']
lines = []
for child in children:
result = generate_plain_lines(child, parent + f"{key}.")
if result is not None:
lines.append(result)
else:
old_value = processing_value(every_dict['old_value'])
new_value = processing_value(every_dict['new_value'])
lines.append(f"Property '{parent}{key}' was updated. "
f"From {old_value} to {new_value}")
elif changes == 'IN_SECOND':
value = processing_value(value)
if isinstance(value, dict):
lines.append(f"Property '{parent}{key}' was added with value: "
f"[complex value]")
else:
lines.append(f"Property '{parent}{key}' was added with value: "
f"{value}")
elif changes == 'IN_FIRST':
value = processing_value(value)
lines.append(f"Property '{parent}{key}' was removed")
return '\n'.join(lines)
result = '\n'.join(lines)
return result
elif node_type == 'ADDED':
value = processing_value(value)
return f"Property {parent}{key} was added with value: {value}"
elif node_type == 'DELETED':
return f"Property {parent}{key} was removed"
elif node_type == 'CHANGED':
old_value = processing_value(diff_tree.get('old_value'))
new_value = processing_value(diff_tree.get('new_value'))
return f"Property {parent}{key} was updated."\
f" From {old_value} to {new_value}"
114 changes: 29 additions & 85 deletions gendiff/generate_stylish_lines.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,67 +2,6 @@
GAP = 4
LEFT_SHIFT = 2

dfflst = {'type': 'root',
'children': [{'key': 'common',
'value': {'type': 'root',
'children': [{'key': 'follow',
'value': False,
'node_type': 'ADDED'},
{'key': 'setting1',
'value': 'Value 1',
'node_type': 'SAME'},
{'key': 'setting2',
'value': 200,
'node_type': 'DELETED'},
{'key': 'setting3',
'old_value': True,
'new_value': None,
'node_type': 'CHANGED'},
{'key': 'setting4',
'value': 'blah blah',
'node_type': 'ADDED'},
{'key': 'setting5',
'value': {'key5': 'value5'},
'node_type': 'ADDED'},
{'key': 'setting6',
'value': {'type': 'root',
'children': [{'key': 'doge',
'value': {'type': 'root',
'children': [{'key': 'wow',
'old_value': '',
'new_value': 'so '
'much',
'node_type': 'CHANGED'}]},
'node_type': 'NESTED'},
{'key': 'key',
'value': 'value',
'node_type': 'SAME'},
{'key': 'ops',
'value': 'vops',
'node_type': 'ADDED'}]},
'node_type': 'NESTED'}]},
'node_type': 'NESTED'},
{'key': 'group1',
'value': {'type': 'root',
'children': [{'key': 'baz',
'old_value': 'bas',
'new_value': 'bars',
'node_type': 'CHANGED'},
{'key': 'foo',
'value': 'bar',
'node_type': 'SAME'},
{'key': 'nest',
'old_value': {'key': 'value'},
'new_value': 'str',
'node_type': 'CHANGED'}]},
'node_type': 'NESTED'},
{'key': 'group2',
'value': {'abc': 12345, 'deep': {'id': 45}},
'node_type': 'DELETED'},
{'key': 'group3',
'value': {'deep': {'id': {'number': 45}}, 'fee': 100500},
'node_type': 'ADDED'}]}


def make_string(key, value, depth, diff=' '):
if isinstance(value, bool):
Expand All @@ -83,31 +22,36 @@ def make_string(key, value, depth, diff=' '):


def generate_stylish_lines(diff_tree, depth=0):
if diff_tree is None or len(diff_tree) == 0:
return ''
lines = []
children = diff_tree['children']
for child in children:
key = child.get('key')
value = child.get('value')
node_type = child.get('node_type')
if node_type == 'NESTED':
lines.append(f"{' ' * ((depth + 1) * GAP - LEFT_SHIFT)} {key}: " + '{')
result = generate_stylish_lines(child.get('value'), depth + 1)
key = diff_tree.get('key')
value = diff_tree.get('value')
node_type = diff_tree.get('node_type')
if node_type == 'root':
children = diff_tree['children']
lines = []
lines.append('{')
for child in children:
result = generate_stylish_lines(child, depth + DEPTH_STEP)
lines.append(result)
elif node_type == 'DELETED':
lines.append(make_string(key, value, depth + 1, '-'))
elif node_type == 'ADDED':
lines.append(make_string(key, value, depth + 1, '+'))
elif node_type == 'CHANGED':
lines.append(make_string(key, child.get('old_value'), depth + 1, '-'))
lines.append(make_string(key, child.get('new_value'), depth + 1, '+'))
else:
lines.append(make_string(key, value, depth + 1))
lines.append(f"{' ' * (depth * GAP - LEFT_SHIFT)} " + '}')
return '\n'.join(lines)

lines.append('}')
return '\n'.join(lines)
elif node_type == 'NESTED':
children = diff_tree['children']
lines = []
for child in children:
result = generate_stylish_lines(child, depth + 1)
lines.append(result)
result = '\n'.join(lines)
return f"{' ' * (depth * GAP)}{key}: " + '{\n'\
f"{result}\n{' ' * (depth * GAP)}" + '}'
elif node_type == 'DELETED':
return make_string(key, value, depth, '-')
elif node_type == 'ADDED':
return make_string(key, value, depth, '+')
elif node_type == 'CHANGED':
return f"{make_string(key, diff_tree.get('old_value'), depth, '-')}\n"\
f"{make_string(key, diff_tree.get('new_value'), depth, '+')}"
else:
return f"{make_string(key, value, depth)}"

print(generate_stylish_lines(dfflst))


1 change: 1 addition & 0 deletions gendiff/scripts/gen_diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from gendiff import generate_diff
from pprint import pprint


def main():
args = parse_args()
pprint(generate_diff(args.first_file, args.second_file, args.format), sort_dicts=False)
Expand Down
70 changes: 27 additions & 43 deletions gendiff/tests/test_diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,51 +10,35 @@ def read_file(path_to_expected_file):
return file.read()


diff_expected_nested = [{'key': 'common', 'value': [{'key': 'follow', 'value': False, 'changes': 'IN_SECOND'}, {'key': 'setting1', 'value': 'Value 1', 'changes': 'SAME'}, {'key': 'setting2', 'value': 200, 'changes': 'IN_FIRST'}, {'key': 'setting3', 'old_value': True, 'new_value': None, 'changes': 'CHANGED'}, {'key': 'setting4', 'value': 'blah blah', 'changes': 'IN_SECOND'}, {'key': 'setting5', 'value': {'key5': 'value5'}, 'changes': 'IN_SECOND'}, {'key': 'setting6', 'value': [{'key': 'doge', 'value': [{'key': 'wow', 'old_value': '', 'new_value': 'so much', 'changes': 'CHANGED'}], 'changes': 'CHANGED'}, {'key': 'key', 'value': 'value', 'changes': 'SAME'}, {'key': 'ops', 'value': 'vops', 'changes': 'IN_SECOND'}], 'changes': 'CHANGED'}], 'changes': 'CHANGED'}, {'key': 'group1', 'value': [{'key': 'baz', 'old_value': 'bas', 'new_value': 'bars', 'changes': 'CHANGED'}, {'key': 'foo', 'value': 'bar', 'changes': 'SAME'}, {'key': 'nest', 'old_value': {'key': 'value'}, 'new_value': 'str', 'changes': 'CHANGED'}], 'changes': 'CHANGED'}, {'key': 'group2', 'value': {'abc': 12345, 'deep': {'id': 45}}, 'changes': 'IN_FIRST'}, {'key': 'group3', 'value': {'deep': {'id': {'number': 45}}, 'fee': 100500}, 'changes': 'IN_SECOND'}]
diff_expected_flat = [{'key': 'follow', 'value': False, 'changes': 'IN_FIRST'}, {'key': 'host', 'value': 'hexlet.io', 'changes': 'SAME'}, {'key': 'proxy', 'value': '123.234.53.22', 'changes': 'IN_FIRST'}, {'key': 'timeout', 'old_value': 50, 'new_value': 20, 'changes': 'CHANGED'}, {'key': 'verbose', 'value': True, 'changes': 'IN_SECOND'}]


def test_construct_diff():
f1, f2 = transform_to_dict('gendiff/tests/fixtures/file4_for_test.json',
'gendiff/tests/fixtures/file5_for_test.json')
f3, f4 = transform_to_dict('gendiff/tests/fixtures/file1_for_test.yml',
'gendiff/tests/fixtures/file2_for_test.yml')
diff_expected_nested = read_file('gendiff/tests/fixtures/except_diff_nested.txt')
diff_expected_flat = read_file('gendiff/tests/fixtures/except_diff_flat.py')
result1 = construct_diff(f1, f2)
result2 = construct_diff(f3, f4)
# assert result1 == diff_expected_nested
assert result2 == diff_expected_flat

# [{'key': 'follow', 'value': False, 'changes': 'IN_FIRST'}, {'key': 'host', 'value': 'hexlet.io', 'changes': 'SAME'}, {'key': 'proxy', 'value': '123.234.53.22', 'changes': 'IN_FIRST'}, {'key': 'timeout', 'old_value': 50, 'new_value': 20, 'changes': 'CHANGED'}, {'key': 'verbose', 'value': True, 'changes': 'IN_SECOND'}]

# "[{'key': 'follow', 'value': False, 'changes': 'IN_FIRST'}, {'key': 'host', 'value': 'hexlet.io', 'changes': 'SAME'}, {'key': 'proxy', 'value': '123.234.53.22', 'changes': 'IN_FIRST'}, {'key': 'timeout', 'old_value': 50, 'new_value': 20, 'changes': 'CHANGED'}, {'key': 'verbose', 'value': True, 'changes': 'IN_SECOND'}]"

test_construct_diff()

def test_generate_stylish_lines():
flat_file_1, flat_file_2 = transform_to_dict('gendiff/tests/fixtures/file1_for_test.json',
'gendiff/tests/fixtures/file2_for_test.json')
nested_file_1, nested_file_2 = transform_to_dict('gendiff/tests/fixtures/file4_for_test.json',
'gendiff/tests/fixtures/file5_for_test.json')
diff_flat = construct_diff(nested_file_1, nested_file_2)
diff_nested = construct_diff(nested_file_1, nested_file_2)
verif_flat = read_file('gendiff/tests/fixtures/expect_flat_stylish.txt')
verif_nested = read_file('gendiff/tests/fixtures/expect_nested_stylish.txt')
assert generate_stylish_lines(diff_expected_flat) == verif_flat
assert generate_stylish_lines(diff_expected_nested) == verif_nested


def test_generate_plain_lines():
verif_flat = read_file('gendiff/tests/fixtures/expect_flat_plain.txt')
verif_nested = read_file('gendiff/tests/fixtures/expect_nested_plain.txt')
assert generate_plain_lines(diff_expected_flat) == verif_flat
assert generate_plain_lines(diff_expected_nested) == verif_nested


def test_generate_json():
verif_json = read_file('gendiff/tests/fixtures/except_to_json.txt')
assert python_to_json(diff_expected_nested) == verif_json


def test_empty_files():
verif_empty = read_file('gendiff/tests/fixtures/expect_empty_files.txt')
empty_file = None
assert generate_stylish_lines(empty_file) == verif_empty
assert generate_plain_lines(empty_file) == verif_empty
assert generate_stylish_lines(diff_flat) == verif_flat
assert generate_stylish_lines(diff_nested) == verif_nested


# def test_generate_plain_lines():
# verif_flat = read_file('gendiff/tests/fixtures/expect_flat_plain.txt')
# verif_nested = read_file('gendiff/tests/fixtures/expect_nested_plain.txt')
# assert generate_plain_lines(diff_expected_flat) == verif_flat
# assert generate_plain_lines(diff_expected_nested) == verif_nested
#
#
# def test_generate_json():
# verif_json = read_file('gendiff/tests/fixtures/except_to_json.txt')
# assert python_to_json(diff_expected_nested) == verif_json
#
#
# def test_empty_files():
# verif_empty = read_file('gendiff/tests/fixtures/expect_empty_files.txt')
# empty_file = None
# assert generate_stylish_lines(empty_file) == verif_empty
# assert generate_plain_lines(empty_file) == verif_empty


0 comments on commit 344381e

Please sign in to comment.