"""
File checkparams.py
Version 2.0
Written by ll.snark
Type Checking in Python using decorators
Use the decorator checkparams to check (only unnamed) parameters type
Use the decorator checkreturn to check a return value type :
@checkreturn(int)
@checkparams(int,int)
def ajoute(a,b) :
if a<0 : return "No negative numbers"
return a+b
Then Try :
ajoute(5,6)
ajoute(5,"Argh")
ajoute(-4,6)
Version 2.0
(
with help from ActiveState members... :
-better type checking
-removed unused lines
-used functools.wraps to copy __name__ and __doc__
)
Note that the preceding decorated function checks if the parameters are
type int or a subtype of int (this is a different behaviour from version 1,
but I think it's better)
Consequently, you can check only the second parameter, for instance, writing :
@checkparams(object,int)
def ajoute(a,c) :
...
Indeed, type of parameter a will always be a subclass of object.
"""
import functools
def checkparams(*params) :
def decorator(fonc) :
@functools.wraps(fonc)
def foncm(*pnn,**pn) :
for i,par in enumerate(zip(pnn,params)) :
if not isinstance(par[0],par[1]) :
raise TypeError(foncm.__name__+" Param "+str(i)+" ("+str(par[0])+") is not "+str(par[1]))
r=fonc(*pnn,**pn)
return r
return foncm
return decorator
def checkreturn(tor) :
def decorator(fonc) :
@functools.wraps(fonc)
def foncm(*pnn,**pn) :
r=fonc(*pnn,**pn)
if not isinstance(r,tor) :
print(type(r))
raise TypeError(foncm.__name__+" : Return value ("+str(r)+") is not "+str(tor))
return r
return foncm
return decorator
if __name__=='__main__' :
@checkreturn(int)
@checkparams(int,int)
def ajoute(a,b) :
""" Just a sample function to test decorators. """
if a<0 : return "No negative numbers"
return a+b
print(ajoute(5,6))
print(ajoute(0,"foo"))
print(ajoute(-3,4))
Diff to Previous Revision
--- revision 1 2012-11-16 16:23:32
+++ revision 2 2012-11-19 13:15:35
@@ -1,5 +1,6 @@
"""
File checkparams.py
+Version 2.0
Written by ll.snark
Type Checking in Python using decorators
@@ -16,33 +17,46 @@
ajoute(5,6)
ajoute(5,"Argh")
ajoute(-4,6)
+
+Version 2.0
+(
+with help from ActiveState members... :
+ -better type checking
+ -removed unused lines
+ -used functools.wraps to copy __name__ and __doc__
+)
+
+Note that the preceding decorated function checks if the parameters are
+type int or a subtype of int (this is a different behaviour from version 1,
+but I think it's better)
+Consequently, you can check only the second parameter, for instance, writing :
+@checkparams(object,int)
+def ajoute(a,c) :
+ ...
+Indeed, type of parameter a will always be a subclass of object.
"""
-
+import functools
def checkparams(*params) :
def decorator(fonc) :
+ @functools.wraps(fonc)
def foncm(*pnn,**pn) :
for i,par in enumerate(zip(pnn,params)) :
- if type(par[0])!=par[1] :
+ if not isinstance(par[0],par[1]) :
raise TypeError(foncm.__name__+" Param "+str(i)+" ("+str(par[0])+") is not "+str(par[1]))
r=fonc(*pnn,**pn)
return r
- foncm.__name__=fonc.__name__
- foncm.__doc__=fonc.__doc__
return foncm
return decorator
def checkreturn(tor) :
def decorator(fonc) :
+ @functools.wraps(fonc)
def foncm(*pnn,**pn) :
r=fonc(*pnn,**pn)
- if type(r)!=tor :
+ if not isinstance(r,tor) :
print(type(r))
raise TypeError(foncm.__name__+" : Return value ("+str(r)+") is not "+str(tor))
return r
- if hasattr(fonc,'__oldname__') :
- foncm.__oldname__=fonc.__oldname__
- foncm.__name__=fonc.__name__
- foncm.__doc__=fonc.__doc__
return foncm
return decorator