Package: runtype
Runtype is a collection of run-time type utilities for Python.It is::runner: Fast! Uses an internal typesystem for maximum performance.:brain: Smart! Supportstyping, forward-references, constraints, auto-casting, and more.:gear: Configurative! Write your own type system, and use it withdataclassanddispatch.Modules:star:validation- Provides a smarter alternative toisinstanceandissubclass, with support for thetypingmodule, and type constraints.:star:dataclass- Adds run-time type validation to the built-in dataclass.Improves dataclass ergonomics.Supports most mypy constructs, liketypingand 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-v1 with pure Python (read here):star:dispatch- Provides fast multiple-dispatch for functions and methods, via a decorator.Dispatch on multiple argumentsFullspecificityresolutionSupports mypy, by utilizing the@overloaddecoratorInspired by Julia.:star:type utilities- Provides a set of classes to implement your own type-system.Supports generics, constraints, phantom typesUsed by runtype itself, to emulate the Python type-system.DocsRead the docs here:https://runtype.readthedocs.io/InstallpipinstallruntypeNo dependencies.Requires Python 3.6 or up.ExamplesValidation (Isa & Subclass)Useisaandissubclassas a smarter alternative to the builtin isinstance & issubclass -fromruntypeimportisa,issubclassassertisa({'a':1},dict[str,int])# == Trueassertnotisa({'a':'b'},dict[str,int])# == Falseassertissubclass(dict[str,int],typing.Mapping[str,int])# == Trueassertnotissubclass(dict[str,int],typing.Mapping[int,str])# == FalseDataclassesfromruntypeimportdataclass@dataclass(check_types='cast')# Cast values to the target type, when applicableclassPerson:name:strbirthday:datetime=None# Implicit optionalinterests:list[str]=[]# The list is copied for each instanceprint(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]))# TypeError: [Person] Attribute 'interests' expected value of type list[str]. Instead got ['a', 1]#     Failed on item: 1, expected type strMultiple DispatchRuntype dispatches according to the most specific type match -fromruntypeimportmultidispatchasmd@mddefmul(a:list,b:list):return[mul(i,j)fori,jinzip(a,b,strict=True)]@mddefmul(a:list,b:Any):return[ai*bforaiina]@mddefmul(a:Any,b:list):return[bi*bforbiinb]@mddefmul(a:Any,b:Any):returna*bassertmul("a",4)=="aaaa"# Any, Anyassertmul([1,2,3],2)==[2,4,6]# list, Anyassertmul([1,2],[3,4])==[3,8]# list, listDispatch can also be used for extending the dataclass builtin__init__:@dataclass(frozen=False)classPoint:x:int=0y:int=0@mddef__init__(self,points:list|tuple):self.x,self.y=points@mddef__init__(self,points:dict):self.x=points['x']self.y=points['y']# Test constructorsp0=Point()# Default constructorassertp0==Point(0,0)# Default constructorassertp0==Point([0,0])# User constructorassertp0==Point((0,0))# User constructorassertp0==Point({"x":0,"y":0})# User constructorLicenseRuntype uses theMIT license.DonateIf you like Runtype and want to show your appreciation, you can do so at mypatreon page, orko-fi page.