This repository has been archived by the owner on Aug 28, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Breaks out the definition, documentation and validation of Indicator parameters to a separate class. Like other parts of Indicator, the params_class is provided to each indicator and used to validate them. Any class which needs a different set of IndicatorParams is free to override with its own definition. See params.py for more documentation about IndicatorParams specifics
- Loading branch information
CloudNiner
committed
Dec 9, 2016
1 parent
bf699ae
commit cd28b65
Showing
7 changed files
with
224 additions
and
59 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
|
||
class ValidationError(Exception): | ||
pass | ||
|
||
|
||
class IndicatorParams(object): | ||
""" Superclass used to define parameters necessary for an Indicator class to function | ||
This class defines the defaults for all indicators, which are all optional. | ||
New IndicatorParams subclasses should implement a new validate_paramname(self, value) | ||
method for each parameter they add. This method should: | ||
- Return a default value if the parameter is optional | ||
- Raise indicators.params.ValidationError(message) if the value is invalid | ||
- Ensure the paramname is added to the self.PARAMS iterable | ||
After calling validate(), the validated parameter values are available as instance attributes. | ||
""" | ||
PARAMS = ('models', 'years', 'agg', 'units',) | ||
|
||
def __init__(self, query_params, available_units, default_units): | ||
""" | ||
@param query_params (dict[str:str]): Dict of key/value pairs to parse | ||
@param available_units (Iterable[str]): List of unit strings this class should check the | ||
'units' query_params against | ||
@param default_units (string): Default value for 'units' to set if none provided | ||
in query_params | ||
""" | ||
self._params = query_params | ||
self._available_units = available_units | ||
self._default_units = default_units | ||
self.validated = False | ||
|
||
def validate(self): | ||
""" Validate all parameters found in self.PARAMS """ | ||
for param in self.PARAMS: | ||
value = self._params.get(param, None) | ||
validation_fn = getattr(self, 'validate_' + param) | ||
clean_value = validation_fn(value) | ||
setattr(self, param, clean_value) | ||
self.validated = True | ||
|
||
def validate_models(self, value): | ||
return self._check_is_string('models', value) if value is not None else None | ||
|
||
def validate_years(self, value): | ||
return self._check_is_string('years', value) if value is not None else None | ||
|
||
def validate_agg(self, value): | ||
return self._check_is_string('agg', value) if value is not None else None | ||
|
||
def validate_units(self, value): | ||
if value is None: | ||
value = self._default_units | ||
if value not in self._available_units: | ||
raise ValidationError('Unit {} must be one of {}'.format(value, self._available_units)) | ||
return value | ||
|
||
def __repr__(self): | ||
""" Override repr to improve class self-documentation """ | ||
representation = { | ||
'validated': self.validated, | ||
'PARAMS': self.PARAMS, | ||
} | ||
if self.validated: | ||
for p in self.PARAMS: | ||
representation[p] = getattr(self, p) | ||
else: | ||
for k, v in self._params.iteritems(): | ||
representation[k] = v | ||
return str(representation) | ||
|
||
def _check_is_string(self, param, value): | ||
""" Private helper method to raise ValidationError if value is not a string """ | ||
if not isinstance(value, basestring): | ||
raise ValidationError('{} must be a string comma separated list'.format(param)) | ||
return value | ||
|
||
|
||
class PercentileIndicatorParams(IndicatorParams): | ||
""" Extend IndicatorParams with a non-optional 'percentile' parameter """ | ||
|
||
PARAMS = IndicatorParams.PARAMS + ('percentile',) | ||
|
||
def validate_percentile(self, value): | ||
if value is None: | ||
raise ValidationError('percentile param required') | ||
try: | ||
int_value = int(value) | ||
except ValueError: | ||
raise ValidationError('percentile param must be an integer') | ||
if int_value < 1 or int_value > 99: | ||
raise ValidationError('percentile param must be within the range (0-100)') | ||
return int_value |
Oops, something went wrong.