Skip to content

erezsh/runtype

master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

alt text

Runtype is a collection of run-time type utilities for Python.

It is:

🏃 Fast! Uses an internal typesystem for maximum performance.

🧠 Smart! Supports typing, forward-references, constraints, auto-casting, and more.

⚙️ Configurative! Write your own type system, and use it with dataclass and dispatch.


Modules

  • validation - Provides a smarter alternative to isinstance and issubclass, with support for the typing module, and type constraints.

  • dataclass - Adds run-time type validation to the built-in dataclass.

    • Improves dataclass ergonomics.
    • Supports most mypy constructs, like typing and forward-references (foo: 'Bar').
    • 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.
    • Twice faster than Pydantic (read here)
  • dispatch - Provides fast multiple-dispatch for functions and methods, via a decorator.

    • Inspired by Julia.
  • 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.

Build Status codecov

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.