Skip to content

Commit f96289d

Browse files
authored
Merge pull request #3512 from WikiWatershed/tt/further-validate-gwlfe-input
2 parents 75f6c4c + 27aacab commit f96289d

File tree

2 files changed

+34
-44
lines changed

2 files changed

+34
-44
lines changed

src/mmw/apps/geoprocessing_api/validation.py

+25-34
Original file line numberDiff line numberDiff line change
@@ -74,15 +74,9 @@ def validate_uuid(uuid):
7474

7575

7676
def validate_gwlfe_prepare(data):
77-
area_of_interest = data.get('area_of_interest')
78-
wkaoi = data.get('wkaoi')
79-
huc = data.get('huc')
8077
layer_overrides = data.get('layer_overrides', {})
8178

82-
if not check_gwlfe_only_one([area_of_interest, wkaoi, huc]):
83-
error = ('Invalid parameter: One and only one type of area object'
84-
' (area_of_interest, wkaoi, or huc) is allowed')
85-
raise ValidationError(error)
79+
check_exactly_one_provided(['area_of_interest', 'wkaoi', 'huc'], data)
8680

8781
not_valid_layers = check_layer_overrides_keys(layer_overrides)
8882

@@ -102,30 +96,21 @@ def validate_gwlfe_prepare(data):
10296
raise ValidationError(error)
10397

10498

105-
def validate_gwlfe_run(input, job_uuid):
106-
if not check_gwlfe_only_one([input, job_uuid]):
107-
error = ('Invalid parameter: Only one type of prepared input'
108-
'(input JSON or job_uuid) is allowed')
109-
raise ValidationError(error)
110-
111-
if not check_gwlfe_run_input(input):
112-
error = ("Invalid input: Please use the full result "
113-
"of gwlf-e/prepare endpoint's result object")
114-
raise ValidationError(error)
115-
116-
117-
def check_gwlfe_only_one(params):
118-
if sum(map(check_is_none, params)) == 1:
119-
return True
120-
else:
121-
return False
99+
def validate_gwlfe_run(input):
100+
missing_keys = [k for k in GWLFE_INPUT_KEYS if k not in input]
101+
if missing_keys:
102+
raise ValidationError(f'Provided `input` is missing: {missing_keys}')
122103

123104

124-
def check_is_none(v):
125-
if v is None:
126-
return 0
127-
else:
128-
return 1
105+
def check_exactly_one_provided(one_of: list, params: dict):
106+
# Dictionary for just the keys of which we want one of
107+
one_of_params = {k: params.get(k) for k in one_of}
108+
# List of keys with not None values
109+
not_none_keys = [k for k, v in one_of_params.items() if v is not None]
110+
if len(not_none_keys) != 1:
111+
raise ValidationError(
112+
f'Must provide exactly one of: {one_of}. '
113+
f'You provided values for: {not_none_keys}')
129114

130115

131116
def check_layer_overrides_keys(layers):
@@ -144,11 +129,6 @@ def check_streams_layer_overrides(layers):
144129
return layers['__STREAMS__'] in STREAM_LAYER_OVERRIDES
145130

146131

147-
def check_gwlfe_run_input(input):
148-
result = all(el in input for el in settings.GWLFE_DEFAULTS.keys())
149-
return result
150-
151-
152132
def create_layer_overrides_keys_not_valid_msg(layers):
153133
error = 'These layers are not standard layers for layer overrides: '
154134
for layler in layers:
@@ -171,3 +151,14 @@ def create_layer_overrides_land_not_valid_msg(values):
171151
]
172152

173153
STREAM_LAYER_OVERRIDES = ['drb', 'nhdhr', 'nhd']
154+
155+
# These are not present in GWLFE_DEFAULTS, but are necessary for running GWLF-E
156+
GWLFE_INPUT_KEYS = list(settings.GWLFE_DEFAULTS.keys()) + [
157+
'AEU', 'Acoef', 'AgLength', 'AgSlope3', 'AgSlope3To8', 'Area', 'AvKF',
158+
'AvSlope', 'CN', 'DayHrs', 'GrNitrConc', 'GrPhosConc', 'Grow', 'KF', 'KV',
159+
'LS', 'ManNitr', 'ManPhos', 'MaxWaterCap', 'NumNormalSys', 'P', 'PhosConc',
160+
'PointFlow', 'PointNitr', 'PointPhos', 'Prec', 'RecessionCoef',
161+
'SedAFactor', 'SedDelivRatio', 'SedNitr', 'SedPhos', 'StreamLength',
162+
'Temp', 'TotArea', 'UrbAreaTotal', 'UrbLength', 'WeatherStations',
163+
'WxYrBeg', 'WxYrEnd', 'WxYrs', 'n23', 'n23b', 'n24', 'n24b', 'n41', 'n41j',
164+
'n41k', 'n41l', 'n42', 'n42b', 'n46e', 'n46f']

src/mmw/apps/geoprocessing_api/views.py

+9-10
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@
4343
from apps.geoprocessing_api.throttling import (BurstRateThrottle,
4444
SustainedRateThrottle)
4545

46-
from apps.geoprocessing_api.validation import (validate_rwd,
46+
from apps.geoprocessing_api.validation import (check_exactly_one_provided,
47+
validate_rwd,
4748
validate_uuid,
4849
validate_gwlfe_prepare,
4950
validate_gwlfe_run)
@@ -1679,8 +1680,7 @@ def _parse_aoi(data):
16791680

16801681

16811682
def _parse_subbasin_input(request):
1682-
if 'wkaoi' not in request.data and 'huc' not in request.data:
1683-
raise ValidationError('Must specify exactly one of: WKAoI ID or HUC')
1683+
check_exactly_one_provided(['wkaoi', 'huc'], request.data)
16841684

16851685
serializer = AoiSerializer(data=request.data)
16861686
serializer.is_valid(raise_exception=True)
@@ -1704,16 +1704,17 @@ def _parse_gwlfe_input(request, raw_input=True):
17041704
mods = request.data.get('modifications', list())
17051705
hash = request.data.get('inputmod_hash', '')
17061706

1707+
one_of = ['input', 'job_uuid'] if raw_input else ['job_uuid']
1708+
1709+
check_exactly_one_provided(one_of, request.data)
1710+
17071711
if raw_input:
17081712
model_input = request.data.get('input')
17091713

17101714
if model_input:
1711-
validate_gwlfe_run(model_input, job_uuid)
1712-
return model_input, job_uuid, mods, hash
1715+
validate_gwlfe_run(model_input)
17131716

1714-
if not job_uuid:
1715-
raise ValidationError('Either `input` or `job_uuid` '
1716-
'must be specified.')
1717+
return model_input, job_uuid, mods, hash
17171718

17181719
if not validate_uuid(job_uuid):
17191720
raise ValidationError(f'Invalid `job_uuid`: {job_uuid}')
@@ -1729,6 +1730,4 @@ def _parse_gwlfe_input(request, raw_input=True):
17291730

17301731
model_input = json.loads(input_job.result)
17311732

1732-
validate_gwlfe_run(model_input, job_uuid)
1733-
17341733
return model_input, job_uuid, mods, hash

0 commit comments

Comments
 (0)