Runtime typechecking without annotations
Project description
PyTypeUtils
A runtime type-checking library which is not based on annotations and has support for numpy and scipy.
Features
This has documentation, unit tests for all API functions, and readable error messages. This detects numpy and torch and, if they exist, provides additional functions for each.
Installation
pip install pytypeutils
Usage
As a precondition test:
import pytypeutils as tus
import typing
def foo(a: int, b: typing.Union[int, float]):
tus.check(a=(a, int), b=(b, (int, float)))
return 7
foo(3, 3) # no error!
foo(3, 3.0) # no error!
foo(3.0, 3) # ValueError: expected a is <class 'int'> but got 3.0 (type(a)=<class 'float'>)
Inside unit tests:
import unittest
import pytypeutils as tus
def foo(a: int):
return 2 * a
class MyTester(unittest.TestCase):
def test_foo_giveint_returnsint(self):
res = foo(2)
tus.check(res=(res, int))
This detects if numpy is installed and adds pytypeutils.check_ndarrays
if
it is:
import pytypeutils as tus
import typing
import numpy as np
def feature_means(pts: np.ndarray):
"""Returns the mean of the features for the given points,
where pts is in the shape (num_samples, num_features)"""
tus.check_ndarrays(
pts=(pts, ('num_samples', 'num_features'), ('float32', 'float64')))
res = pts.mean(0)
tus.check_ndarrays(
res=(res, [('num_features', pts.shape[1])], pts.dtype)
)
return res
feature_means(np.random.uniform(0, 1, (10, 4))) # works
feature_means(np.random.uniform(0, 1, (10, 4, 2)))
# ValueError: expected pts.shape is (num_samples=any, num_features=any)
# but has shape (10, 4, 2)
This detects if torch is installed and adds pytypeutils.check_tensors
if
it is:
import pytypeutils as tus
import typing
import torch
def feature_means(pts: torch.tensor):
'''Returns the mean of the features for the given points,
where pts is in the shape (num_samples, num_features)'''
tus.check_tensors(
pts=(pts, ('num_samples', 'num_features'), ('float32', 'float64')))
res = pts.mean(0)
tus.check_tensors(
res=(res, [('num_features', pts.shape[1])], pts.dtype)
)
return res
feature_means(torch.randn(10, 4)) # works
feature_means(torch.randn(10, 4, 2))
# ValueError: expected pts.shape is (num_samples=any, num_features=any)
# but has shape (10, 4, 2)
Why this type library?
Annotation type libraries, such as pytypes and typeguard can be great if it's reasonable to express things in terms of typing hints. However, this can often be tedious and it doesn't translate well to unit tests, quick snippets, or for a quick debug command in the middle of a function call. This library lets you get reasonable type errors which you can write and optionally remove quickly, without having to do type checking on an entire functions parameters. Furthermore, the built-in extensions for numpy and pytorch reduce a tremendous amount of boilerplate if you are using those libraries and want some sanity checks.
API
>>> help(pytypeutils)
Help on package pytypeutils:
NAME
pytypeutils - Various generic functions and imports for pytypeutils.
PACKAGE CONTENTS
np_checks
torch_checks
utils
FUNCTIONS
check(**kwargs)
Each keyword argument corresponds to an argument whose type will be
checked. The key is used for printing out error messages and the value
is a tuple describing the object to be checked and how it is to be checked.
Example:
```
import pytypeutils as tus
import typing
def foo(a: int, b: typing.Union[int, float]):
tus.check(a=(a, int), b=(b, (int, float)))
```
check_callable(**kwargs)
Verifies that every value is callable. If not, raises an error
check_listlike(**kwargs)
Verifies that the given list-like objects have contents of a particular
type. The keys are used for error messages, the values should be a tuple
of the form (list, content types, optional length or (minl, maxl)).
If there are more than 100 elements in any of the lists, 100 elements are
sampled at random.
Example:
import pytypeutils as tus
import typing
def foo(a: typing.List[str], b: typing.List[typing.Union[int, float]]):
tus.check(a=(a, (tuple, list)), b=(b, (tuple, list)))
tus.check_listlike(a=(a, str), b=(b, (int, float), (0, 5)))
# all elements of a are str
# b has 0-5 elements inclusive, each of which is an int or float
>>> help(pytypeutils.check_ndarrays)
Help on function check_ndarrays in module pytypeutils.np_checks:
check_ndarrays(**kwargs)
Checks to verify the given arguments are numpy arrays with the given
specifications. The keys are used for error messages and the values are
tuples of the form (arr, expected shape, expected dtype). The expected
shape may be None not to check shape information, or a tuple of dimension
descriptions which can be None (for an any-size dimension), a str (for
an any-size dimension with a name for error messages), an int (for a
dimension of a particular size), or a tuple (str, int) where the str is
the name of the dimension and the int is the size of the dimension. The
dtype may be a tuple of numpy datatypes as strings or types, or None for
any dtype.
Example:
import pytypeutils as tus
import typing
import numpy as np
def feature_means(pts: np.ndarray):
'''Returns the mean of the features for the given points,
where pts is in the shape (num_samples, num_features)'''
tus.check_ndarrays(
pts=(pts, ('num_samples', 'num_features'), ('float32', 'float64')))
res = pts.mean(0)
tus.check_ndarrays(
res=(res, [('num_features', pts.shape[1])], pts.dtype)
)
return res
>>> help(pytypeutils.check_tensors)
Help on function check_tensors in module pytypeutils.torch_checks:
check_tensors(**kwargs)
Checks to verify the given arguments are torch tensors with the given
specifications. The keys are used for error messages and the values are
tuples of the form (arr, expected shape, expected dtype). The expected
shape may be None not to check shape information, or a tuple of dimension
descriptions which can be None (for an any-size dimension), a str (for
an any-size dimension with a name for error messages), an int (for a
dimension of a particular size), or a tuple (str, int) where the str is
the name of the dimension and the int is the size of the dimension. The
dtype may be a tuple of numpy datatypes as strings or types, or None for
any dtype.
Example:
import pytypeutils as tus
import typing
import torch
def feature_means(pts: torch.tensor):
'''Returns the mean of the features for the given points,
where pts is in the shape (num_samples, num_features)'''
tus.check_tensors(
pts=(pts, ('num_samples', 'num_features'), ('float32', 'float64')))
res = pts.mean(0)
tus.check_tensors(
res=(res, [('num_features', pts.shape[1])], pts.dtype)
)
return res
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file pytypeutils-0.0.1.tar.gz
.
File metadata
- Download URL: pytypeutils-0.0.1.tar.gz
- Upload date:
- Size: 6.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.13.0 pkginfo/1.4.2 requests/2.19.1 setuptools/41.0.1 requests-toolbelt/0.9.1 tqdm/4.26.0 CPython/3.7.0
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 1701ac1d5404bf877fc1e9634bbcaaec7b0fe25f1295b2ac5d02ec19f8fe84d6 |
|
MD5 | 43bd53c90cd01b3693559114d2029ffc |
|
BLAKE2b-256 | bd596ce6815b9d20aa62498a177c06ffe239874f6b7ab43dff3890bccdfae91b |
File details
Details for the file pytypeutils-0.0.1-py3-none-any.whl
.
File metadata
- Download URL: pytypeutils-0.0.1-py3-none-any.whl
- Upload date:
- Size: 10.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/1.13.0 pkginfo/1.4.2 requests/2.19.1 setuptools/41.0.1 requests-toolbelt/0.9.1 tqdm/4.26.0 CPython/3.7.0
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 7fba56d0c540e2843f73a08f049a1889e730843597b876f383080403c9777b1c |
|
MD5 | b75aded1442c931d11355431e5f893bd |
|
BLAKE2b-256 | d7d313ad18e458a5f36a10accae9967ffa68ea4e964b0914767eb503a34eaf97 |