runtype
runtype copied to clipboard
Utilities for run-time type validation and multiple dispatch
Runtype is a collection of run-time type utilities for Python.
It is:
:runner: Fast! Uses an internal typesystem for maximum performance.
:brain: Smart! Supports typing
, constraints, auto-casting, and much more.
:gear: Configurative! Write your own type system, and use it with dataclass and dispatch.
Modules
-
:star: validation - Provides a smarter alternative to
isinstance
andissubclass
, with support for thetyping
module, and type constraints. -
:star: dataclass - Adds run-time type validation to the built-in dataclass.
- Improves dataclass ergonomics.
- Supports automatic value casting, Pydantic-style. (Optional, off by default)
- Supports types with constraints. (e.g.
String(max_length=10)
) - Supports optional sampling for faster validation of big lists and dicts.
- 40% faster than Pydantic (read here)
-
:star: dispatch - Provides fast multiple-dispatch for functions and methods, via a decorator.
- Inspired by Julia.
-
:star: type utilities - Provides a set of classes to implement your own type-system.
- Used by runtype itself, to emulate the Python type-system.
Docs
Read the docs here: https://runtype.readthedocs.io/
Install
pip install runtype
No dependencies.
Requires Python 3.6 or up.
Examples
Validation (Isa & Subclass)
from typing import Dict, Mapping
from runtype import isa, issubclass
print( isa({'a': 1}, Dict[str, int]) )
#> True
print( isa({'a': 'b'}, Dict[str, int]) )
#> False
print( issubclass(Dict[str, int], Mapping[str, int]) )
#> True
print( issubclass(Dict[str, int], Mapping[int, str]) )
#> False
Dataclasses
from typing import List
from datetime import datetime
from runtype import dataclass
@dataclass(check_types='cast') # Cast values to the target type, when applicable
class Person:
name: str
birthday: datetime = None # Optional
interests: List[str] = [] # The list is copied for each instance
print( Person("Beetlejuice") )
#> Person(name='Beetlejuice', birthday=None, interests=[])
print( Person("Albert", "1955-04-18T00:00", ['physics']) )
#> Person(name='Albert', birthday=datetime.datetime(1955, 4, 18, 0, 0), interests=['physics'])
print( Person("Bad", interests=['a', 1]) )
# Traceback (most recent call last):
# ...
# TypeError: [Person] Attribute 'interests' expected value of type list[str]. Instead got ['a', 1]
# Failed on item: 1, expected type str
Multiple Dispatch
from runtype import Dispatch
dp = Dispatch()
@dp
def append(a: list, b):
return a + [b]
@dp
def append(a: tuple, b):
return a + (b,)
@dp
def append(a: str, b: str):
return a + b
print( append([1, 2, 3], 4) )
#> [1, 2, 3, 4]
print( append((1, 2, 3), 4) )
#> (1, 2, 3, 4)
print( append('foo', 'bar') )
#> foobar
print( append('foo', 4) )
# Traceback (most recent call last):
# ...
# runtype.dispatch.DispatchError: Function 'append' not found for signature (<class 'str'>, <class 'int'>)
License
Runtype uses the MIT license.
Donate
If you like Runtype and want to show your appreciation, you can do so at my patreon page, or ko-fi page.