Skip to main content

Argument check decorator

Project description

# argcheck

A decorator based implementation of argument checks, whose code is largely referenced from [zipline/utils/input_validation](https://github.com/quantopian/zipline/blob/master/zipline/utils/input_validation.py), provides various functionality in argument validation.
* *expect_kinds*: decorator to check argument dtype kinds
* *expect_types*: decorator to check argument types
* *optional*: helper of *expect_types* to deal with default argument
* *expect_element*: decorator to check if argument takes a value in expected set of elements
* *expect_bounded* and *expect_strictly_bounded*: decorators to check argument lies inclusively or exclusively within the bounds
* *expect_dimensions*: decorator to check if argument takes in a numpy array with a specific dimensionality
* *coerce* and *coerce_types*: decorators that deal with type coercions


### Usage
``` python
from argcheck import *
```

### Install

``` python
pip install argcheck
```

### Example



##### *expect_kinds*: decorator that verifies inputs have expected dtype kinds
``` python
from numpy import int64, int32, float32

@expect_kinds(x='i')
def foo(x):
return x

foo(int64(2)) # 2
foo(int32(2)) # 2
foo(float32(2))
# Traceback (most recent call last):
# ...
# TypeError: ...foo() expected a numpy object of kind 'i' for argument 'x',
# but got 'f' instead.

```

##### *expect_types*: decorator that verifies inputs have expected types

``` python
@expect_types(x=int, y=str)
def foo(x, y):
return x, y


foo(2, '3') # (2, '3')


# foo(2.0, '3')
# Traceback (most recent call last):
# ...
# TypeError: ...foo() expected a value of type int for argument 'x',
# but got float instead.


```

works on class member functions with default argument as well

``` python
class test(object):
@expect_types(y=(int, str))
def __init__(self, x, y=3):
pass


test(x=3) # OK
test(x=3, y=5) # OK
test(x=1, y=[3])
# Traceback (most recent call last):
# ...
# TypeError: __init__() expected a value of type int or str for argument 'y',
# but got list instead

```


##### *optional*: helper for use with *expect_types* when an input can be `type_` or `None`.

``` python
isinstance({}, optional(dict)) # True
isinstance(None, optional(dict)) # True
isinstance(1, optional(dict)) # False
isinstance(1, optional(dict, int)) # True
```
``` python

# used with expect_types
class test2(object):
@expect_types(y=optional(int, str))
def __init__(self, x, y=None):
pass


test2(3) # OK
test2(3, [2])
# TypeError: __init__() expected a value of type int or str or NoneType for argument 'y',
# but got list instead.

```


##### *expect_element*: decorator that verifies inputs are elements of some expected collection

``` python
@expect_element(x=('a', 'b'))
def foo(x):
return x.upper()

foo('a') # 'A'
foo('c')
# ValueError: foo() expected a value in ('a', 'b') for argument 'x',
# but got 'c' instead.
```


##### *expect_bounded*: decorator verifying that inputs fall INCLUSIVELY between bounds
* Bounds should be passed as a pair of ``(min_value, max_value)``.
``None`` may be passed as ``min_value`` or ``max_value`` to signify that
the input is only bounded above or below.

``` python
@expect_bounded(x=(1, 5))
def foo(x):
return x + 1


foo(3) # 4
foo(6)
# ValueError: foo() expected a value inclusively between 1 and 5 for argument 'x',
# but got 6 instead


```


``` python
@expect_bounded(x=(1, None))
def foo(x):
return x + 1


foo(3) # 4
foo(0)
# ValueError: foo() expected a value greater than or equal to 1 for argument 'x',
# but got 0 instead.


```


##### *expect_strictly_bounded*: decorator verifying that inputs fall EXCLUSIVELY between bounds

``` python

@expect_strictly_bounded(x=(1, 5))
def foo(x):
return x + 1

foo(5)
# ValueError: foo() expected a value exclusively between 1 and 5 for argument 'x',
# but got 5 instead.
```


##### *expect_dimensions*: decorator that verifies inputs are numpy arrays with a specific dimensionality

``` python

from numpy import array

@expect_dimensions(x=1, y=2)
def foo(x, y):
return x[0] + y[0, 0]

foo(array([1, 1]), array([[1, 1], [2, 2], [3, 4]])) #ok
foo(array([1, 1]), array([[1, 1], [2, 2]])) # ok
foo(array([1, 1]), array([1, 1]))

# ValueError: foo() expected a 2-D array for argument 'y',
# but got a 1-D array instead.

```

##### *coerce*: decorator that coerces inputs of a given type by passing them to a callable

``` python
@preprocess(x=coerce(str, int, base=2), y=coerce(str, int, base=2))
def add_binary_strings(x, y):
return bin(x + y)[2:]

print add_binary_strings('101', '001') # 110


```


##### *coerce_types*: decorator that applies type coercions
* input param: dict[str -> (type, callable)]
* Keyword arguments mapping function parameter names to pairs of
(from_type, to_type)

``` python
@coerce_types(x=(float, int), y=(int, str))
def func(x, y):
return (x, y)

func(1.0, 3) # (1, '3')

```

Please see [example](/argcheck/example.py) for details

Project details


Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page