Skip to content

Commit e565dea

Browse files
committed
Add Python code and package
1 parent 52aa136 commit e565dea

File tree

4 files changed

+146
-0
lines changed

4 files changed

+146
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
11
/nodejs/node_modules
2+
/python3/build
3+
/python3/dist
4+
/python3/*.egg-info

python3/fsoft_diff_patch/__init__.py

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
#!/usr/bin/env python3
2+
3+
import json
4+
5+
null = None
6+
7+
8+
def _make_deep_patch_list(old_list: list, new_list: list):
9+
patch = {}
10+
11+
# expand old_list to the same length of new_list
12+
old_list = old_list + [null] * (len(new_list) - len(old_list))
13+
14+
for i in range(0, len(new_list)):
15+
old_value = old_list[i]
16+
new_value = new_list[i]
17+
18+
if old_value is null:
19+
patch[str(i)] = new_value
20+
elif new_value is null:
21+
patch[str(i)] = null
22+
elif type(new_value) is list:
23+
sub_patch = _make_deep_patch_list(old_value, new_value)
24+
if sub_patch:
25+
patch[str(i)] = sub_patch
26+
elif type(new_value) is dict:
27+
sub_patch = _make_deep_patch_dict(old_value, new_value)
28+
if sub_patch:
29+
patch[str(i)] = sub_patch
30+
elif old_value != new_value:
31+
patch[str(i)] = new_value
32+
33+
return patch
34+
35+
36+
def _make_deep_patch_dict(old_dict: dict, new_dict: dict):
37+
patch = {}
38+
keys = new_dict.keys()
39+
40+
for key in keys:
41+
old_value = old_dict.get(key, null)
42+
new_value = new_dict.get(key, null)
43+
44+
if old_value is null:
45+
patch[key] = new_value
46+
elif new_value is null:
47+
patch[key] = null
48+
elif type(new_value) is list:
49+
sub_patch = _make_deep_patch_list(old_value, new_value)
50+
if sub_patch:
51+
patch[key] = sub_patch
52+
elif type(new_value) is dict:
53+
sub_patch = _make_deep_patch_dict(old_value, new_value)
54+
if sub_patch:
55+
patch[key] = sub_patch
56+
elif old_value != new_value:
57+
patch[key] = new_value
58+
59+
# now scan old_dict keys and delete the ones that are not present in new_dict
60+
keys = old_dict.keys()
61+
for key in keys:
62+
if key not in new_dict:
63+
patch[key] = null
64+
65+
return patch
66+
67+
68+
def diff(old_object, new_object):
69+
"""
70+
diffData = diff(oldObject, newObject)
71+
72+
creates a patch object that can be used to update the oldObject to the newObject
73+
the patch object has the same structure as the newObject, but with the following differences:
74+
fields that are equal in both objects are not present in the patch object
75+
fields that are different in both objects are present in the patch object, with the newObject value
76+
fields that are NOT present in the oldObject are present in the patch object
77+
fields that are NOT present in the newObject are present in the patch object with the value null
78+
"""
79+
80+
if type(old_object) is dict:
81+
return _make_deep_patch_dict(old_object, new_object)
82+
83+
if type(old_object) is list:
84+
return _make_deep_patch_list(old_object, new_object)
85+
86+
87+
def patch(old_object, diff_data):
88+
new_object = json.loads(json.dumps(old_object))
89+
keys = diff_data.keys()
90+
91+
for key in keys:
92+
new_value = diff_data[key]
93+
try:
94+
key_number = int(key)
95+
except ValueError:
96+
key_number = -1
97+
98+
# this is an array modification
99+
if key_number >= 0:
100+
if key_number >= len(new_object):
101+
new_object.append(new_value)
102+
else:
103+
new_object[key_number] = patch(new_object[key_number], new_value)
104+
else:
105+
# this is a key/value modification
106+
107+
if new_value is None:
108+
del new_object[key]
109+
continue
110+
111+
if key not in new_object:
112+
new_object[key] = new_value
113+
continue
114+
115+
if isinstance(new_value, dict):
116+
new_object[key] = patch(new_object[key], new_value)
117+
else:
118+
new_object[key] = new_value
119+
120+
return new_object

python3/mk_package.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/bin/bash
2+
3+
rm -Rf build *.egg-info dist
4+
python3 setup.py sdist bdist_wheel
5+
twine upload dist/*

python3/setup.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from setuptools import setup, find_packages
2+
3+
setup(
4+
name="fsoft_diff_patch",
5+
version="0.1.0",
6+
description="Deep compare two objects and produces a diffData to transform object1 to object2",
7+
author="Fabio Rotondo",
8+
author_email="fabio.rotondo@gmail.com",
9+
packages=find_packages(),
10+
install_requires=[
11+
# Aggiungi qui eventuali dipendenze
12+
],
13+
classifiers=[
14+
"Development Status :: 5 - Production/Stable",
15+
"License :: OSI Approved :: MIT License",
16+
"Programming Language :: Python :: 3",
17+
],
18+
)

0 commit comments

Comments
 (0)