43 lines
1.3 KiB
Python
43 lines
1.3 KiB
Python
|
#!/usr/bin/env python
|
||
|
|
||
|
from agate.aggregations.base import Aggregation
|
||
|
from agate.data_types import Boolean
|
||
|
|
||
|
|
||
|
class First(Aggregation):
|
||
|
"""
|
||
|
Returns the first value that passes a test.
|
||
|
|
||
|
If the test is omitted, the aggregation will return the first value in the column.
|
||
|
|
||
|
If no values pass the test, the aggregation will raise an exception.
|
||
|
|
||
|
:param column_name:
|
||
|
The name of the column to check.
|
||
|
:param test:
|
||
|
A function that takes a value and returns `True` or `False`. Test may be
|
||
|
omitted when checking :class:`.Boolean` data.
|
||
|
"""
|
||
|
def __init__(self, column_name, test=None):
|
||
|
self._column_name = column_name
|
||
|
self._test = test
|
||
|
|
||
|
def get_aggregate_data_type(self, table):
|
||
|
return table.columns[self._column_name].data_type
|
||
|
|
||
|
def validate(self, table):
|
||
|
column = table.columns[self._column_name]
|
||
|
data = column.values()
|
||
|
|
||
|
if self._test is not None and len([d for d in data if self._test(d)]) == 0:
|
||
|
raise ValueError('No values pass the given test.')
|
||
|
|
||
|
def run(self, table):
|
||
|
column = table.columns[self._column_name]
|
||
|
data = column.values()
|
||
|
|
||
|
if self._test is None:
|
||
|
return data[0]
|
||
|
|
||
|
return next((d for d in data if self._test(d)))
|