-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathProject-1_1.py
138 lines (123 loc) · 3.4 KB
/
Project-1_1.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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# Validating one dictionary structure against template dictionary.
def match_keys(data, valid, path):
data_keys = data.keys()
valid_keys = valid.keys()
extra_keys = data_keys - valid_keys
missing_keys = valid_keys - data_keys
if missing_keys or extra_keys:
missing_msg = ('missing keys: '+
', '.join({path+'.'+str(key) for key in missing_keys})
) if missing_keys else ''
extras_msg = ('extra keys: ' +
', '.join({path + '.' + str(key) for key in extra_keys})
) if extra_keys else ''
return False, ' '.join((missing_msg,',', extras_msg))
else:
return True, None
def match_types(data, template, path):
for key, value in template.items():
if isinstance(value, dict):
template_type = dict
else:
template_type = value
data_value = data.get(key, object())
if not isinstance(data_value, template_type):
err_msg = ('incorrect type: ' + path + '.' + key +
' -> expected ' + template_type.__name__+
', found ' + type(data_value).__name__)
return False, err_msg
return True, None
def recurse_validate(data, template, path):
is_ok, err_msg = match_keys(data, template, path)
if not is_ok:
return False, err_msg
is_ok, err_msg = match_types(data, template, path)
if not is_ok:
return False, err_msg
dictionary_type_keys = {key for key,value in template.items()
if isinstance(value, dict)}
for key in dictionary_type_keys:
sub_path = path + '.'+ str(key)
sub_template = template[key]
sub_data = data[key]
is_ok, err_msg = recurse_validate(sub_data, sub_template, sub_path)
if not is_ok:
return False, err_msg
return True, None
def validate(data, template):
return recurse_validate(data, template, '')
template = {
'user_id': int,
'name': {
'first': str,
'last': str
},
'bio': {
'dob': {
'year': int,
'month': int,
'day': int
},
'birthplace': {
'country': str,
'city': str
}
}
}
john = {
'user_id': 100,
'name': {
'first': 'John',
'last': 'Cleese'
},
'bio': {
'dob': {
'year': 1939,
'month': 11,
'day': 27
},
'birthplace': {
'country': 'United Kingdom',
'city': 'Weston-super-Mare'
}
}
}
eric = {
'user_id': 101,
'name': {
'first': 'Eric',
'last': 'Idle'
},
'bio': {
'dob': {
'year': 1943,
'month': 3,
'day': 29
},
'birthplace': {
'country': 'United Kingdom'
}
}
}
michael = {
'user_id': 102,
'name': {
'first': 'Michael',
'last': 'Palin'
},
'bio': {
'dob': {
'year': 1943,
'month': 'May',
'day': 5
},
'birthplace': {
'country': 'United Kingdom',
'city': 'Sheffield'
}
}
}
persons = ((john, 'John'),(eric, 'Eric'), (michael, 'Michael'))
for person, name in persons:
is_ok, err_msg = validate(person, template)
print(f'{name}: valid={is_ok}: {err_msg}')