Show More
@@ -1,55 +1,55 b'' | |||||
1 | # dicthelpers.py - helper routines for Python dicts |
|
1 | # dicthelpers.py - helper routines for Python dicts | |
2 | # |
|
2 | # | |
3 | # Copyright 2013 Facebook |
|
3 | # Copyright 2013 Facebook | |
4 | # |
|
4 | # | |
5 | # This software may be used and distributed according to the terms of the |
|
5 | # This software may be used and distributed according to the terms of the | |
6 | # GNU General Public License version 2 or any later version. |
|
6 | # GNU General Public License version 2 or any later version. | |
7 |
|
7 | |||
8 | def diff(d1, d2, default=None): |
|
8 | def diff(d1, d2, default=None): | |
9 | '''Return all key-value pairs that are different between d1 and d2. |
|
9 | '''Return all key-value pairs that are different between d1 and d2. | |
10 |
|
10 | |||
11 | This includes keys that are present in one dict but not the other, and |
|
11 | This includes keys that are present in one dict but not the other, and | |
12 | keys whose values are different. The return value is a dict with values |
|
12 | keys whose values are different. The return value is a dict with values | |
13 | being pairs of values from d1 and d2 respectively, and missing values |
|
13 | being pairs of values from d1 and d2 respectively, and missing values | |
14 | represented as default.''' |
|
14 | treated as default, so if a value is missing from one dict and the same as | |
|
15 | default in the other, it will not be returned.''' | |||
15 | res = {} |
|
16 | res = {} | |
16 | if d1 is d2: |
|
17 | if d1 is d2: | |
17 | # same dict, so diff is empty |
|
18 | # same dict, so diff is empty | |
18 | return res |
|
19 | return res | |
19 |
|
20 | |||
20 | for k1, v1 in d1.iteritems(): |
|
21 | for k1, v1 in d1.iteritems(): | |
21 | if k1 in d2: |
|
22 | v2 = d2.get(k1, default) | |
22 |
|
|
23 | if v1 != v2: | |
23 |
|
|
24 | res[k1] = (v1, v2) | |
24 | res[k1] = (v1, v2) |
|
|||
25 | else: |
|
|||
26 | res[k1] = (v1, default) |
|
|||
27 |
|
25 | |||
28 | for k2 in d2: |
|
26 | for k2 in d2: | |
29 | if k2 not in d1: |
|
27 | if k2 not in d1: | |
30 |
|
|
28 | v2 = d2[k2] | |
|
29 | if v2 != default: | |||
|
30 | res[k2] = (default, v2) | |||
31 |
|
31 | |||
32 | return res |
|
32 | return res | |
33 |
|
33 | |||
34 | def join(d1, d2, default=None): |
|
34 | def join(d1, d2, default=None): | |
35 | '''Return all key-value pairs from both d1 and d2. |
|
35 | '''Return all key-value pairs from both d1 and d2. | |
36 |
|
36 | |||
37 | This is akin to an outer join in relational algebra. The return value is a |
|
37 | This is akin to an outer join in relational algebra. The return value is a | |
38 | dict with values being pairs of values from d1 and d2 respectively, and |
|
38 | dict with values being pairs of values from d1 and d2 respectively, and | |
39 | missing values represented as default.''' |
|
39 | missing values represented as default.''' | |
40 | res = {} |
|
40 | res = {} | |
41 |
|
41 | |||
42 | for k1, v1 in d1.iteritems(): |
|
42 | for k1, v1 in d1.iteritems(): | |
43 | if k1 in d2: |
|
43 | if k1 in d2: | |
44 | res[k1] = (v1, d2[k1]) |
|
44 | res[k1] = (v1, d2[k1]) | |
45 | else: |
|
45 | else: | |
46 | res[k1] = (v1, default) |
|
46 | res[k1] = (v1, default) | |
47 |
|
47 | |||
48 | if d1 is d2: |
|
48 | if d1 is d2: | |
49 | return res |
|
49 | return res | |
50 |
|
50 | |||
51 | for k2 in d2: |
|
51 | for k2 in d2: | |
52 | if k2 not in d1: |
|
52 | if k2 not in d1: | |
53 | res[k2] = (default, d2[k2]) |
|
53 | res[k2] = (default, d2[k2]) | |
54 |
|
54 | |||
55 | return res |
|
55 | return res |
@@ -1,53 +1,59 b'' | |||||
1 | from mercurial.dicthelpers import diff, join |
|
1 | from mercurial.dicthelpers import diff, join | |
2 | import unittest |
|
2 | import unittest | |
3 | import silenttestrunner |
|
3 | import silenttestrunner | |
4 |
|
4 | |||
5 | class testdicthelpers(unittest.TestCase): |
|
5 | class testdicthelpers(unittest.TestCase): | |
6 | def test_dicthelpers(self): |
|
6 | def test_dicthelpers(self): | |
7 | # empty dicts |
|
7 | # empty dicts | |
8 | self.assertEqual(diff({}, {}), {}) |
|
8 | self.assertEqual(diff({}, {}), {}) | |
9 | self.assertEqual(join({}, {}), {}) |
|
9 | self.assertEqual(join({}, {}), {}) | |
10 |
|
10 | |||
11 | d1 = {} |
|
11 | d1 = {} | |
12 | d1['a'] = 'foo' |
|
12 | d1['a'] = 'foo' | |
13 | d1['b'] = 'bar' |
|
13 | d1['b'] = 'bar' | |
14 | d1['c'] = 'baz' |
|
14 | d1['c'] = 'baz' | |
15 |
|
15 | |||
16 | # same identity |
|
16 | # same identity | |
17 | self.assertEqual(diff(d1, d1), {}) |
|
17 | self.assertEqual(diff(d1, d1), {}) | |
18 | self.assertEqual(join(d1, d1), {'a': ('foo', 'foo'), |
|
18 | self.assertEqual(join(d1, d1), {'a': ('foo', 'foo'), | |
19 | 'b': ('bar', 'bar'), |
|
19 | 'b': ('bar', 'bar'), | |
20 | 'c': ('baz', 'baz')}) |
|
20 | 'c': ('baz', 'baz')}) | |
21 |
|
21 | |||
22 | # vs empty |
|
22 | # vs empty | |
23 | self.assertEqual(diff(d1, {}), {'a': ('foo', None), |
|
23 | self.assertEqual(diff(d1, {}), {'a': ('foo', None), | |
24 | 'b': ('bar', None), |
|
24 | 'b': ('bar', None), | |
25 | 'c': ('baz', None)}) |
|
25 | 'c': ('baz', None)}) | |
26 | self.assertEqual(diff(d1, {}), {'a': ('foo', None), |
|
26 | self.assertEqual(diff(d1, {}), {'a': ('foo', None), | |
27 | 'b': ('bar', None), |
|
27 | 'b': ('bar', None), | |
28 | 'c': ('baz', None)}) |
|
28 | 'c': ('baz', None)}) | |
29 |
|
29 | |||
30 | d2 = {} |
|
30 | d2 = {} | |
31 | d2['a'] = 'foo2' |
|
31 | d2['a'] = 'foo2' | |
32 | d2['b'] = 'bar' |
|
32 | d2['b'] = 'bar' | |
33 | d2['d'] = 'quux' |
|
33 | d2['d'] = 'quux' | |
34 |
|
34 | |||
35 | self.assertEqual(diff(d1, d2), {'a': ('foo', 'foo2'), |
|
35 | self.assertEqual(diff(d1, d2), {'a': ('foo', 'foo2'), | |
36 | 'c': ('baz', None), |
|
36 | 'c': ('baz', None), | |
37 | 'd': (None, 'quux')}) |
|
37 | 'd': (None, 'quux')}) | |
38 | self.assertEqual(join(d1, d2), {'a': ('foo', 'foo2'), |
|
38 | self.assertEqual(join(d1, d2), {'a': ('foo', 'foo2'), | |
39 | 'b': ('bar', 'bar'), |
|
39 | 'b': ('bar', 'bar'), | |
40 | 'c': ('baz', None), |
|
40 | 'c': ('baz', None), | |
41 | 'd': (None, 'quux')}) |
|
41 | 'd': (None, 'quux')}) | |
42 |
|
42 | |||
43 | # with default argument |
|
43 | # with default argument | |
44 | self.assertEqual(diff(d1, d2, 123), {'a': ('foo', 'foo2'), |
|
44 | self.assertEqual(diff(d1, d2, 123), {'a': ('foo', 'foo2'), | |
45 | 'c': ('baz', 123), |
|
45 | 'c': ('baz', 123), | |
46 | 'd': (123, 'quux')}) |
|
46 | 'd': (123, 'quux')}) | |
47 | self.assertEqual(join(d1, d2, 456), {'a': ('foo', 'foo2'), |
|
47 | self.assertEqual(join(d1, d2, 456), {'a': ('foo', 'foo2'), | |
48 | 'b': ('bar', 'bar'), |
|
48 | 'b': ('bar', 'bar'), | |
49 | 'c': ('baz', 456), |
|
49 | 'c': ('baz', 456), | |
50 | 'd': (456, 'quux')}) |
|
50 | 'd': (456, 'quux')}) | |
51 |
|
51 | |||
|
52 | # check that we compare against default | |||
|
53 | self.assertEqual(diff(d1, d2, 'baz'), {'a': ('foo', 'foo2'), | |||
|
54 | 'd': ('baz', 'quux')}) | |||
|
55 | self.assertEqual(diff(d1, d2, 'quux'), {'a': ('foo', 'foo2'), | |||
|
56 | 'c': ('baz', 'quux')}) | |||
|
57 | ||||
52 | if __name__ == '__main__': |
|
58 | if __name__ == '__main__': | |
53 | silenttestrunner.main(__name__) |
|
59 | silenttestrunner.main(__name__) |
General Comments 0
You need to be logged in to leave comments.
Login now