Package: typingx
typingxHow many times have you wanted to check the shape of your data either in application code or while testing?
With this library, you can leveragetypingtypes at runtime to do that!This is even more powerful when used with generic standard collections (e.g.list[str]) introduced in python 3.9 and new union operator|introduced in python 3.10. If you want to use them with older version, a backportfuture-typingexists!Example# Check if `x` is a string or an integerisinstancex(x,str|int)# Check if `my_list` has only numbersisinstancex(my_list,list[int|float])# Check if `my_set` has only integers greater than 2 with at least 3 distinct onesGt2Int=Annotated[int,Constraints(gt=2)]isinstancex(my_set,Annotated[set[Gt2Int],Constraints(min_length=3)])# or `typing.Set`# Check deeper the shape of `my_dict`isinstancex(my_dict,{'a':int,'b':bool,...:str})# shortcut for `typing.TypedDict('TD', {'a': int, 'b': bool, __extra__: str})`# Check if all the keys are 1 lower case letter and values are integers with 1 digitOneLowerStr=Annotated[str,Constraints(regex='^[a-z]$')]OneDigitUInt=Annotated[int,Constraints(ge=0,lt=10)]isinstancex(my_dict,dict[OneLowerStr,OneDigitUInt])@func_checkdefmy_func(a:int,b:Annotated[int,Constraints(ge=5)])->Annotated[int,Constraints(le=10)]:returna+btry:my_func(1,4)exceptTypeErrorase:assertstr(e)=="Input b (value: 4) is not a valid Annotated[int, Constraints(ge=5)]"try:my_func(5,6)exceptTypeErrorase:assertstr(e)=="Output (value: 11) is not a valid Annotated[int, Constraints(le=10)]"Sincetypingchanged a lot since python3.6, this library also makes sure the whole behaviour
is consistent with3.10for all python versions.It hence provides:isinstancex: likeisinstanceandissubclassbut withtypingtypes and extra types provided by this library:warning: using a tuple as second parameter will validate againstTuplex. If you want to check against multiple types(int, str), wrap it intoUnion[(int, str)]!issubclassx: same asisinstancexbut forissubclassfunc_check: a decorator to check inputs and output of a function based on annotationget_argsandget_originthat have the exact same behaviour as thetypingmodule with python 3.10, no matter which python version is used!is_literal,is_newtype,is_typeddicthelpersmosttypingtypes but with homogeneous behaviour (e.g. with3.8, this libray will choosetyping_extensions.TypedDictinstead oftyping.TypedDictsince the latter doesn't store information to distinguish optional and required keys)extanded types:TypedDictwith...field to allow type checking on optional fieldsextra types:ListxandTuplex: more sophisticated versions ofListandTupleto add...anywhere in the parametersInstallationpipinstalltypingxisinstancexfromcollectionsimportChainMap,Counterfromtypingximport*T,U=TypeVar('T'),TypeVar('U')# AnnotatedGT2=Annotated[int,Constraints(gt=2)]assertisinstancex(1,int)isTrueassertisinstancex(1,GT2)isFalseassertisinstancex(3,GT2)isTrueassertisinstancex([3,3],list[GT2])isTrueBetween2And5=Annotated[Union[float,int],Constraints(ge=2,le=5)]assertisinstancex(3,Between2And5)isTrueassertisinstancex(3.5,Between2And5)isTrueassertisinstancex('3.5',Between2And5)isFalseassertisinstancex(3,Annotated[int,Constraints(multiple_of=1.5)])isTrueassertisinstancex(3.,Annotated[int,Constraints(multiple_of=1.5)])isFalseassertisinstancex(3.,Annotated[Union[int,float],Constraints(multiple_of=1.5)])isTrueMult1_5AndLe2=Annotated[Union[int,float],Constraints(multiple_of=1.5,le=10)]assertisinstancex(15,Mult1_5AndLe2)isFalseassertisinstancex([3.0,4.5,9],list[Mult1_5AndLe2])isTrueassertisinstancex([3.,4.3],list[Mult1_5AndLe2])isFalseOneLowerStr=Annotated[str,Constraints(regex='^[a-z]$')]OneDigitUInt=Annotated[int,Constraints(ge=0,lt=10)]assertisinstancex({'a':1,'b':2},dict[OneLowerStr,OneDigitUInt])isTrueassertisinstancex({'a':1,'bc':2},dict[OneLowerStr,OneDigitUInt])isFalse# Callabledeff(x:int,y:float)->str:returnf'{x}{y}'assertisinstancex(f,Callable)isTrueassertisinstancex(f,Callable[...,Any])isTrueassertisinstancex(f,Callable[...,str])isTrueassertisinstancex(f,Callable[[int,float],str])isTrueassertisinstancex(f,Callable[[T,float],U][int,str])isTrue# Dictassertisinstancex({"a":1,"b":2},Dict[str,int])isTrueassertisinstancex({"a":1,"b":2},Dict[str,str])isFalseassertisinstancex({"a":1,"b":2},Dict[int,str])isFalseassertisinstancex({"a":1,"b":2},Dict[str,Any])isTrue# Listassertisinstancex([1,2,3],List[int])isTrueassertisinstancex([1,2,"q"],List[int])isFalseassertisinstancex([1,2,"q"],List[Union[str,int]])isTrue# Listxassertisinstancex([1,2,3,4],Listx[int])isFalseassertisinstancex([1,2,3,4],Listx[int,...])isTrueassertisinstancex([1,2,"q"],Listx[int,...,str])isTrueassertisinstancex([1,2,"q","w","e"],Listx[int,...,str])isFalseassertisinstancex([1,2,"q","w","e"],Listx[int,...,str,...])isTrueassertisinstancex([1,2,"q","w",b"xyz","e"],Listx[int,...,str,...])isFalseassertisinstancex([1,2,"q","w",b"xyz","e"],Listx[int,...,Union[str,bytes],...])isTrue# Listx (shortcut)assertisinstancex([1,2,3,4,"q"],[int,...,str])isTrue# Literalassertisinstancex("a",Literal["a"])isTrueassertisinstancex(Literal["a"],Literal["a"])isTrueassertisinstancex("b",Literal["a"])isFalseassertisinstancex("b",Literal["a",Literal[Literal["b"]]])isTrueassertisinstancex(Literal["a","b"],Literal["b","a","c"])isTrue# Mappingassertisinstancex(Counter({"red":4,"blue":2}),Mapping[str,int])isTrueassertisinstancex(ChainMap({"art":"van gogh"},{"music":"bach"}),Mapping[str,str])isTrue# NewTypeUserId=NewType("UserId",int)ProUserId=NewType("ProUserId",UserId)assertisinstancex(1,UserId)isTrueassertisinstancex(1,ProUserId)isTrueassertisinstancex(UserId(1),UserId)isTrueassertisinstancex("3",UserId)isFalse# Noneassertisinstancex([None,None],List[None])isTrueassertisinstancex([None,None],List[NoneType])isTrueassertisinstancex([None,None],List[type(None)])isTrueassertisinstancex([None,None],List[Literal[None]])isTrue# Sequenceassertisinstancex("abc",Sequence[Any])isTrueassertisinstancex("abc",Sequence[int])isFalseassertisinstancex((1,3,5),Sequence[int])isTrue# Setassertisinstancex({"a","b"},Set[str])isTrueassertisinstancex({"a","b"},Set[int])isFalse# Tupleassertisinstancex((),Tuple[()])isTrueassertisinstancex((1,),Tuple[()])isTrueassertisinstancex((1,2),Tuple[int,...])isTrueassertisinstancex((1,2),Tuple[int,int])isTrueassertisinstancex((1,2),Tuple[int,int,int])isFalse# Tuplexassertisinstancex((3,"a","b"),Tuplex[int,str,...])isTrueassertisinstancex((3,"a","b","c"),Tuplex[int,str,...])isTrueassertisinstancex((3,"a","b","c"),Tuplex[int,str,...,bool])isFalseassertisinstancex((3,"a","b","c",True),Tuplex[int,str,...,bool])isTrueassertisinstancex((3,"a","b","c",3),Tuplex[int,str,...,bool])isFalseassertisinstancex((3,"a","b","c",True,False),Tuplex[int,str,...,bool,...])isTrue# Tuplex (shortcut)assertisinstancex((True,"q","q","q","q"),(bool,Literal["q"],...))isTrue# TypeclassUser:...classBaseUser(User):...assertisinstancex(BaseUser,Type[BaseUser])isTrueassertisinstancex(BaseUser,Type[User])isTrueassertisinstancex(User,Type[User])isTrueassertisinstancex(User,Type[BaseUser])isFalse# TypedDictFullMovie=TypedDict("FullMovie",{"name":str,"year":int})classPartialMovie(TypedDict,total=False):name:stryear:intclassExtraMovie(TypedDict):name:stryear:int__extra__:strassertisinstancex({"name":"The Matrix","year":1999},FullMovie)isTrueassertisinstancex({"name":"The Matrix","year":"1999"},FullMovie)isFalseassertisinstancex({"name":"The Matrix"},FullMovie)isFalseassertisinstancex({"name":"The Matrix","year":1999,"extra":"qwe"},FullMovie)isFalseassertisinstancex({"name":"The Matrix","year":1999},PartialMovie)isTrueassertisinstancex({"name":"The Matrix"},PartialMovie)isTrueassertisinstancex({"name":"The Matrix","year":1999,"extra":"qwe"},PartialMovie)isFalseassertisinstancex({"name":"The Matrix","year":1999},ExtraMovie)isTrueassertisinstancex({"name":"The Matrix","year":1999,"q":"w","e":"r"},ExtraMovie)isTrueassertisinstancex({"name":"The Matrix","year":1999,"q":"w","e":1},ExtraMovie)isFalse# TypedDict (shortcut)assertisinstancex({"name":"The Matrix","year":1999,"q":"w","e":"r"},{"name":str,"year":int,...:str})isTrue# Unionassertisinstancex(3,Union[str,int])isTrueassertisinstancex(3,Union[str,float])isFalseassertisinstancex(3.14,Union[int,T,str][bool])isFalseassertisinstancex(3.14,Union[int,T,str][float])isTrueissubclassx (:warning: still in WIP)fromtypingximport*assertissubclassx(int,int)isTrueassertissubclassx(int,object)isTrueassertissubclassx(int,float)isFalseassertissubclassx(int,int|str)isTrueassertissubclassx(tuple[int],tuple)isTrueassertissubclassx(tuple[int],tuple[Any])isTrueassertissubclassx(tuple[int],tuple[Any,...])isTrueassertissubclassx(tuple[int,str],tuple[object,...])isTrueassertissubclassx(tuple[int,str],tuple[Any])isFalseassertissubclassx(tuple[int,int],(int,...))isTrueassertissubclassx(tuple[int,int],(int,str))isFalseassertissubclassx(tuple[int,int],(int,Any))isTrue