Welcome, guest | Sign In | My Account | Store | Cart
""" 
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
 

History