forked from the-gigi/deep
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdeeper.py
111 lines (84 loc) · 2.93 KB
/
deeper.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
from collections import OrderedDict, Mapping, Container
from pprint import pprint
from sys import getsizeof
def deep_compare(a, b, pointer='/'):
if a == b:
return
if type(a) != type(b):
reason = 'Different data types'
extra = str((type(a), type(b)))
x(pointer, reason, extra)
elif type(a) in (set, frozenset):
pointer += 'set()'
if len(a) != len(b):
pointer += 'set()'
reason = 'Different number of items'
extra = str((len(a), len(b)))
x(pointer, reason, extra)
reason = 'Different items'
extra = (a, b)
x(pointer, reason, extra)
for i in range(len(a)):
deep_compare(a[i], b[i], pointer + 'set()'.format(i))
elif type(a) in (list, tuple):
if len(a) != len(b):
pointer += '[]'
reason = 'Different number of items'
extra = str((len(a), len(b)))
x(pointer, reason, extra)
if sorted(a) == sorted(b):
pointer += '[]'
reason = 'Different sort order'
extra = 'N/A'
x(pointer, reason, extra)
for i in range(len(a)):
deep_compare(a[i], b[i], pointer + '[{}]'.format(i))
elif type(a) in (dict, OrderedDict):
if len(a) != len(b):
pointer += '{}'
reason = 'Different number of items'
extra = str((len(a), len(b)))
x(pointer, reason, extra)
if set(a.keys()) != set(b.keys()):
pointer += '{}'
reason = 'Different keys'
extra = (a.keys(), b.keys())
x(pointer, reason, extra)
for k in a:
deep_compare(a[k], b[k], pointer + '[{}]'.format(k))
else:
reason = 'Different objects'
extra = (a, b)
x(pointer, reason, extra)
def x(pointer, reason, extra):
message = 'Objects are not the same. Pointer: {}. Reason: {}. Extra: {}'
raise RuntimeError(message.format(pointer, reason, extra))
def compare(a, b):
try:
deep_compare(a, b, '/')
except RuntimeError as e:
pprint(e.message)
def deep_getsizeof(o, ids):
"""Find the memory footprint of a Python object
This is a recursive function that rills down a Python object graph
like a dictionary holding nested ditionaries with lists of lists
and tuples and sets.
The sys.getsizeof function does a shallow size of only. It counts each
object inside a container as pointer only regardless of how big it
really is.
:param o: the object
:param ids:
:return:
"""
d = deep_getsizeof
if id(o) in ids:
return 0
r = getsizeof(o)
ids.add(id(o))
if isinstance(o, str) or isinstance(0, unicode):
return r
if isinstance(o, Mapping):
return r + sum(d(k, ids) + d(v, ids) for k, v in o.iteritems())
if isinstance(o, Container):
return r + sum(d(x, ids) for x in o)
return r