Skip to content

Commit a1a19ac

Browse files
committed
lib360dataquality: Add check_field_present
Generic test written as a subclass of AdditionalTest that checks for a specific field's existence. These are tests needed for the dashboard project.
1 parent 0fa4edd commit a1a19ac

File tree

1 file changed

+94
-0
lines changed

1 file changed

+94
-0
lines changed
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
from lib360dataquality.cove.threesixtygiving import AdditionalTest
2+
from functools import wraps
3+
4+
5+
class FieldNotPresentBase(AdditionalTest):
6+
"""Checks if any grants do not have a specified field"""
7+
8+
# Field should be overridden and specified as a path
9+
# e.g. /awardDate
10+
def __init__(self, *args, **kwargs):
11+
super().__init__(*args, **kwargs)
12+
13+
self.check_text = {
14+
"heading": "not contain %s field" % self.field,
15+
"message": "Providing %s field helps people to understand the grant information."
16+
% self.field,
17+
}
18+
19+
def process(self, grant, path_prefix):
20+
if not self.field:
21+
raise Exception("Field to check for not set")
22+
23+
if self.check_field(grant) is False:
24+
self.failed = True
25+
self.count += 1
26+
self.json_locations.append(path_prefix + "/id")
27+
28+
self.heading = self.format_heading_count(self.check_text["heading"], verb="do")
29+
self.message = self.check_text["message"]
30+
31+
32+
# exception to false is a decorator rather than handling it in process()
33+
# this is so that we don't get strange interactions with @ignore_errors decorator
34+
# which is already present on the caller of the process function
35+
def exception_to_false(f):
36+
"""If the function returns a KeyError or IndexError exception it is treated as false"""
37+
38+
@wraps(f)
39+
def check(self, grant):
40+
try:
41+
f(self, grant)
42+
return True
43+
except (KeyError, IndexError):
44+
return False
45+
46+
return check
47+
48+
49+
class ClassificationNotPresent(FieldNotPresentBase):
50+
field = "classifications"
51+
52+
@exception_to_false
53+
def check_field(self, grant):
54+
return grant["classifications"]
55+
56+
57+
class BeneficiaryLocationNameNotPresent(FieldNotPresentBase):
58+
field = "beneficiaryLocation/0/name"
59+
60+
@exception_to_false
61+
def check_field(self, grant):
62+
return grant["beneficiaryLocation"][0]["name"]
63+
64+
65+
class BeneficiaryLocationCountryCodeNotPresent(FieldNotPresentBase):
66+
field = "beneficiaryLocation/0/countryCode"
67+
68+
@exception_to_false
69+
def check_field(self, grant):
70+
return grant["beneficiaryLocation"][0]["countryCode"]
71+
72+
73+
class BeneficiaryLocationGeoCodeNotPresent(FieldNotPresentBase):
74+
field = "beneficiaryLocation/0/geoCode"
75+
76+
@exception_to_false
77+
def check_field(self, grant):
78+
return grant["beneficiaryLocation"][0]["geoCode"]
79+
80+
81+
class PlannedDurationNotPresent(FieldNotPresentBase):
82+
field = "plannedDates/0/duration"
83+
84+
@exception_to_false
85+
def check_field(self, grant):
86+
return grant["plannedDates"][0]["duration"]
87+
88+
89+
class GrantProgrammeTitleNotPresent(FieldNotPresentBase):
90+
field = "grantProgramme/0/title"
91+
92+
@exception_to_false
93+
def check_field(self, grant):
94+
return grant["grantProgramme"][0]["title"]

0 commit comments

Comments
 (0)