Skip to content

Commit 99343ea

Browse files
authored
fix error with unhashable types and compare_dicts (piccolo-orm#182)
1 parent 3f184f5 commit 99343ea

File tree

2 files changed

+83
-3
lines changed

2 files changed

+83
-3
lines changed

piccolo/apps/migrations/auto/diffable_table.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,29 @@ def compare_dicts(dict_1, dict_2) -> t.Dict[str, t.Any]:
2020
"""
2121
Returns a new dictionary which only contains key, value pairs which are in
2222
the first dictionary and not the second.
23+
24+
For example:
25+
dict_1 = {'a': 1, 'b': 2}
26+
dict_2 = {'a': 1}
27+
returns {'b': 2}
28+
29+
dict_1 = {'a': 2, 'b': 2}
30+
dict_2 = {'a': 1}
31+
returns {'a': 2, 'b': 2}
32+
2333
"""
24-
return dict(set(dict_1.items()) - set(dict_2.items()))
34+
output = {}
35+
36+
for key, value in dict_1.items():
37+
38+
dict_2_value = dict_2.get(key, ...)
39+
if dict_2_value is ...:
40+
output[key] = value
41+
else:
42+
if dict_2_value != value:
43+
output[key] = value
44+
45+
return output
2546

2647

2748
@dataclass

tests/apps/migrations/auto/test_diffable_table.py

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,75 @@
44
DiffableTable,
55
compare_dicts,
66
)
7-
from piccolo.columns import Varchar
7+
from piccolo.columns import OnDelete, Varchar
88

99

1010
class TestCompareDicts(TestCase):
11-
def test_compare_dicts(self):
11+
def test_simple(self):
12+
"""
13+
Make sure that simple values are compared properly.
14+
"""
1215
dict_1 = {"a": 1, "b": 2}
1316
dict_2 = {"a": 1, "b": 3}
1417
response = compare_dicts(dict_1, dict_2)
1518
self.assertEqual(response, {"b": 2})
1619

20+
def test_missing_keys(self):
21+
"""
22+
Make sure that if one dictionary has keys that the other doesn't,
23+
it works as expected.
24+
"""
25+
dict_1 = {"a": 1}
26+
dict_2 = {"b": 2, "c": 3}
27+
response = compare_dicts(dict_1, dict_2)
28+
self.assertEqual(response, {"a": 1})
29+
30+
def test_list_value(self):
31+
"""
32+
Make sure list values work correctly.
33+
"""
34+
dict_1 = {"a": 1, "b": [1]}
35+
dict_2 = {"a": 1, "b": [2]}
36+
response = compare_dicts(dict_1, dict_2)
37+
self.assertEqual(response, {"b": [1]})
38+
39+
def test_dict_value(self):
40+
"""
41+
Make sure dictionary values work correctly.
42+
"""
43+
dict_1 = {"a": 1, "b": {"x": 1}}
44+
dict_2 = {"a": 1, "b": {"x": 1}}
45+
response = compare_dicts(dict_1, dict_2)
46+
self.assertEqual(response, {})
47+
48+
dict_1 = {"a": 1, "b": {"x": 1}}
49+
dict_2 = {"a": 1, "b": {"x": 2}}
50+
response = compare_dicts(dict_1, dict_2)
51+
self.assertEqual(response, {"b": {"x": 1}})
52+
53+
def test_none_values(self):
54+
"""
55+
Make sure there are no edge cases when using None values.
56+
"""
57+
dict_1 = {"a": None, "b": 1}
58+
dict_2 = {"a": None}
59+
response = compare_dicts(dict_1, dict_2)
60+
self.assertEqual(response, {"b": 1})
61+
62+
def test_enum_values(self):
63+
"""
64+
Make sure Enum values can be compared correctly.
65+
"""
66+
dict_1 = {"a": OnDelete.cascade}
67+
dict_2 = {"a": OnDelete.cascade}
68+
response = compare_dicts(dict_1, dict_2)
69+
self.assertEqual(response, {})
70+
71+
dict_1 = {"a": OnDelete.set_default}
72+
dict_2 = {"a": OnDelete.cascade}
73+
response = compare_dicts(dict_1, dict_2)
74+
self.assertEqual(response, {"a": OnDelete.set_default})
75+
1776

1877
class TestDiffableTable(TestCase):
1978
def test_subtract(self):

0 commit comments

Comments
 (0)