mirror of
https://github.com/wassname/catalyst.git
synced 2026-08-14 12:10:24 +08:00
ENH: Dont allow length=1 regressions/correlations.
They're not meaningful, and they cause warnings from numpy. Implemented in terms of a new preprocessor, `expect_bounded`, which takes a tuple of `upper_bound` and `lower_bound`.
This commit is contained in:
@@ -503,6 +503,97 @@ def expect_element(*_pos, **named):
|
||||
return preprocess(**valmap(_expect_element, named))
|
||||
|
||||
|
||||
def expect_bounded(**named):
|
||||
"""
|
||||
Preprocessing decorator that verifies inputs fall between upper and lower
|
||||
bounds.
|
||||
|
||||
Usage
|
||||
-----
|
||||
>>> @expect_bounded(x=(1, 5))
|
||||
... def foo(x):
|
||||
... return x + 1
|
||||
...
|
||||
>>> foo(1)
|
||||
2
|
||||
>>> foo(5)
|
||||
6
|
||||
>>> foo(6) # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: ...foo() expected a value between 1 and 5 for argument 'x',
|
||||
but got 6 instead.
|
||||
|
||||
Notes
|
||||
-----
|
||||
None can be passed as the lower or upper bound to signify that a value only
|
||||
has an upper or lower bound.
|
||||
|
||||
>>> @expect_bounded(x=(2, None))
|
||||
... def foo(x):
|
||||
... return x
|
||||
...
|
||||
>>> foo(100000)
|
||||
100000
|
||||
>>> foo(1) # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: ...foo() expected a value greater than or equal to 2 for
|
||||
argument 'x', but got 1 instead.
|
||||
|
||||
>>> @expect_bounded(x=(None, 5))
|
||||
... def foo(x):
|
||||
... return x
|
||||
...
|
||||
>>> foo(6) # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: ...foo() expected a value less than or equal to 5 for
|
||||
argument 'x', but got 6 instead.
|
||||
"""
|
||||
def valid_bounds(t):
|
||||
return (
|
||||
isinstance(t, tuple)
|
||||
and len(t) == 2
|
||||
and t != (None, None)
|
||||
)
|
||||
|
||||
for name, bounds in iteritems(named):
|
||||
if not valid_bounds(bounds):
|
||||
raise TypeError(
|
||||
"expect_bounded() expected a tuple of bounds for"
|
||||
" argument '{name}', but got {bounds} instead.".format(
|
||||
name=name,
|
||||
bounds=bounds,
|
||||
)
|
||||
)
|
||||
|
||||
def _expect_bounded(bounds):
|
||||
(lower, upper) = bounds
|
||||
if lower is None:
|
||||
should_fail = lambda value: value > upper
|
||||
predicate_descr = "less than or equal to " + str(upper)
|
||||
elif upper is None:
|
||||
should_fail = lambda value: value < lower
|
||||
predicate_descr = "greater than or equal to " + str(lower)
|
||||
else:
|
||||
should_fail = lambda value: not (lower <= value <= upper)
|
||||
predicate_descr = "between %s and %s" % bounds
|
||||
|
||||
template = (
|
||||
"%(funcname)s() expected a value {predicate}"
|
||||
" for argument '%(argname)s', but got %(actual)s instead."
|
||||
).format(predicate=predicate_descr)
|
||||
|
||||
return make_check(
|
||||
exc_type=ValueError,
|
||||
template=template,
|
||||
pred=should_fail,
|
||||
actual=repr,
|
||||
)
|
||||
return preprocess(**valmap(_expect_bounded, named))
|
||||
|
||||
|
||||
def expect_dimensions(**dimensions):
|
||||
"""
|
||||
Preprocessing decorator that verifies inputs are numpy arrays with a
|
||||
|
||||
Reference in New Issue
Block a user