[Tutor] Argument check

Gregor Lingl glingl at aon.at
Thu May 4 19:15:13 CEST 2006


Hi all,

I've a class with a lot of methods, for which I'd like to check argument types. 
To show you, what I mean, I've written a prototype I'm not really content with.
It goes like this (a bit revised in order to have short codelines (*mail* ;-)):

class BadArgError(Exception):
     def __init__(self, fname, var, typ, val):
         self.fname = fname
         self.var = var
         self.typ = typ
         self.val = val
     def __str__(self):
         return """
     %s: argument %s must be %s!
     %s of %s given.""" % ( self.fname, self.var,
             self.typ, repr(self.val), type(self.val))

def checkargs(fun,locs,*typelist):
     varnames=fun.im_func.func_code.co_varnames[1:]
     fn = fun.__name__
     for var, typ in zip(varnames, typelist):
         ok = isinstance(locs[var],typ)
         if not ok:
             raise BadArgError(fn, var, typ, locs[var])

## classe for testing:

class Z(object):
     pass

class A(object):
     def f(self,x,y):
         checkargs(self.f, locals(), int, str)
     def g(self,a,b,c):
         checkargs(self.g, locals(), (int,float), Z, tuple)


BadArgError works like this (interactive session):

 >>> bae = BadArgError("myfun", "myvar", str, 3)
 >>> raise bae

Traceback (most recent call last):
   File "<pyshell#5>", line 1, in -toplevel-
     raise bae
BadArgError:
     myfun: argument myvar must be <type 'str'>!
     3 of <type 'int'> given.

You see, I want to the error-message to display the name of the function, which 
got the bad argument, the name of the parameter and it's expected type as well 
as the wrong argument.

Examples for it's use:

 >>> z=Z()
 >>> a=A()
 >>> a.f(1,"a")   #ok
 >>> a.f(1,2)

Traceback (most recent call last):
   File "<pyshell#9>", line 1, in -toplevel-
   ...<snip>
     raise BadArgError(fn, var, typ, locs[var])
BadArgError:
     f: argument y must be <type 'str'>!
     2 of <type 'int'> given.
 >>> a.g(.5, z, ())    #ok
 >>> a.g(.5, a, ())

Traceback (most recent call last):
   File "<pyshell#11>", line 1, in -toplevel-
   ...<snip>
     raise BadArgError(fn, var, typ, locs[var])
BadArgError:
     g: argument b must be <class '__main__.Z'>!
     <__main__.A object at 0x00C92F70> of <class '__main__.A'> given.

(One could easily tidy up this output - that's *not* the problem)

I feel it to be cumbersome and ugly, to have to pass the function (method) and 
the locals() dictionary to every call of checkargs.

I'd very much prefer a usage of checkargs similar to:

class A(object):
     def f(self,x,y):
         checkargs(int, str)
     def g(self,a,b,c):
         checkargs((int,float), Z, tuple)

but then chackargs had to get information about its caller (name, locals) from 
elsewhere (the callstack?). I don't know if this is possible at all, not to say 
how to accomplish it.

Do you have some hints?
Where could I find code-examples which solve similar problems?
Would you recommend a different approach?

Regards,

Gregor





-- 
Gregor Lingl
Reisnerstrasse 3/19
A-1030 Wien

Telefon: +43 1 713 33 98
Mobil:   +43 664 140 35 27

Website: python4kids.net



More information about the Tutor mailing list