473,605 Members | 2,240 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Decorator for Enforcing Argument Types

I'm not sure if this has been done before, but I couldn't easily find
any prior work on Google, so here I present a simple decorator for
documenting and verifying the type of function arguments.
Feedback/suggestions/criticism is welcome.

'''
2006.12.21 Created.
'''

import unittest
import inspect

def arguments(*args ):
'''A simple decorator for formally documenting
and verifying argument types.

usage:

@arguments(type 1, type2, [type3.1, type3.2, ..., type3.N],
type4, ..., typeN)
def somefunc(arg1, arg2, arg3, arg4, ..., argN):
do stuff
return

'''
return lambda f:_Arguments(f, *args)

class _Arguments(obje ct):
# todo: extend to verify Zope interfaces
def __init__(self, fn, *args):
self.fn = fn

# create argument type list
self.arguments = []
for arg in args:
if not isinstance(arg, list):
arg = list([arg])
arg = set(arg)
self.arguments. append(arg)

# create name-to-index lookup
argNames, varArgName, varkwName, defaults =
inspect.getargs pec(fn)
assert len(argNames) == len(self.argume nts), 'list of argument
types must match the number of arguments'
self.argNameToI ndex = {}
for i,name in enumerate(argNa mes):
self.argNameToI ndex[name] = i
if defaults and i >= len(self.argume nts)-len(defaults):
# add default type to allowable types

self.arguments[i].add(type(defau lts[i-(len(self.argum ents)-len(defaults))]))

def verify(self, value, i):
'''Returns true if the value matches the allowable types
for the ith argument.'''
if not isinstance(i, int):
if i not in self.argNameToI ndex:
raise Exception, 'unknown argument name: %s' % i
i = self.argNameToI ndex[i]
return type(value) in self.arguments[i]

def verifyAll(self, *values, **kvalues):
'''Returns true if all values matche the allowable types
for their corresponding arguments.'''
for i,value in enumerate(value s):
if not self.verify(val ue, i):
return False
for name,value in kvalues.iterite ms():
if not self.verify(val ue, name):
return False
return True

def __call__(self, *args, **kargs):
assert self.verifyAll( *args, **kargs), 'argument types must be
in the form of %s' % self.arguments
return self.fn(*args, **kargs)

class Test(unittest.T estCase):

def test(self):

@arguments(str, [int, float], list)
def foo(abc, xyz, big=None):
return '%s %s' % (abc, xyz)

self.assertEqua l(type(foo), _Arguments)
self.assertEqua l(len(foo.argum ents), 3)
self.assertEqua l(foo.arguments[2], set([list, type(None)]))
self.assertEqua l(foo.verify('h ow', 0), True)
self.assertEqua l(foo.verify(12 3, 0), False)
self.assertEqua l(foo.verify(12 3, 1), True)
self.assertEqua l(foo.verify(1. 23, 1), True)
self.assertEqua l(foo.verifyAll ('how',123), True)
self.assertEqua l(foo.verifyAll (123,'how'), False)
self.assertEqua l(foo.verifyAll (abc='how',xyz= 123), True)
self.assertEqua l(foo.verifyAll ('how',xyz=123) , True)
self.assertEqua l(foo.verifyAll ('how',xyz='oeu uo'), False)
self.assertEqua l(foo.verifyAll ('how',xyz=123, big=None), True)
self.assertEqua l(foo.verifyAll ('how',xyz=123, big=[1,2,3]),
True)
self.assertEqua l(foo.verifyAll ('how',123,[1,2,3]), True)
self.assertEqua l(foo.verifyAll ('how',123,'aso enhuas'), False)
self.assertTrue (foo('how',123) )
self.assertTrue (foo(abc='how', xyz=123,big=Non e))

if __name__ == '__main__':

unittest.main()

Dec 21 '06 #1
20 1945
"Chris" <ch*******@gmai l.comwrote in message
news:11******** **************@ 79g2000cws.goog legroups.com...
I'm not sure if this has been done before, but I couldn't easily find
any prior work on Google, so here I present a simple decorator for
documenting and verifying the type of function arguments.
Feedback/suggestions/criticism is welcome.
They Python wiki has a page for decorator ideas/submissions, compare yours
to this one:
http://wiki.python.org/moin/PythonDe...348f78db34303e

-- Paul
Dec 21 '06 #2
On Dec 21, 3:57 pm, "Paul McGuire" <p...@austin.rr ._bogus_.comwro te:
"Chris" <chriss...@gmai l.comwrote in messagenews:11* *************** ******@79g2000c ws.googlegroups .com...
I'm not sure if this has been done before, but I couldn't easily find
any prior work on Google, so here I present a simple decorator for
documenting and verifying the type of function arguments.
Feedback/suggestions/criticism is welcome.They Python wiki has a page for decorator ideas/submissions, compare yours
to this one:http://wiki.python.org/moin/PythonDe...-308f2b3507ca9...
Thanks, I was unaware of that page. I designed mine allow for
introspection, so the program can explicitly "see" what types a
function takes and test argument combinations if need be, which that
example doesn't seem to allow. Mine also supports multiple types per
argument. However, I like how that one also checks the return value.

Chris

Dec 21 '06 #3
Chris wrote:
I'm not sure if this has been done before
see example 4 in the original specification:

http://www.python.org/dev/peps/pep-0318/#examples

</F>

Dec 21 '06 #4
Chris wrote:
I'm not sure if this has been done before,
I think this is the best implementation:
http://oakwinter.com/code/typecheck/

I have never used it, but it seems well done.

Bye,
bearophile

Dec 21 '06 #5
Chris a écrit :
I'm not sure if this has been done before,
It has...
but I couldn't easily find
any prior work on Google, so here I present a simple decorator for
documenting and verifying the type of function arguments.
Feedback/suggestions/criticism is welcome.
<my humble opinion>
Python is dynamic, and fighting against the language is IMHO a really
bad idea. The only places where theres a real need for this kind of
stuff are when dealing with the "outside world" (IOW : inputs and
outputs). And then packages like formencode can do much more than mere
type-checking
</my humble opinion>

Dec 21 '06 #6
Bruno Desthuilliers wrote:
<my humble opinion>
Python is dynamic, and fighting against the language is IMHO a really
bad idea. The only places where theres a real need for this kind of
stuff are when dealing with the "outside world" (IOW : inputs and
outputs). And then packages like formencode can do much more than mere
type-checking
</my humble opinion>
Agreed. The worst case I have seen:

An elaborate decorator (similar to the OP's) laboriously checks arg
types. That's IMHO not "consenting adults" territory. But it gets a
whole lot worse when it's applied to a method whose body is like this:

if isinstance(....
action_for_type 1(...
# big snip
elif isinstance(...
action_typeN( ...
# no else statement

Dec 21 '06 #7
John Machin wrote:
Bruno Desthuilliers wrote:
<my humble opinion>
Python is dynamic, and fighting against the language is IMHO a really
bad idea. The only places where theres a real need for this kind of
stuff are when dealing with the "outside world" (IOW : inputs and
outputs). And then packages like formencode can do much more than mere
type-checking
</my humble opinion>

Agreed. The worst case I have seen:

An elaborate decorator (similar to the OP's) laboriously checks arg
types. That's IMHO not "consenting adults" territory. But it gets a
whole lot worse when it's applied to a method whose body is like this:

if isinstance(....
action_for_type 1(...
# big snip
elif isinstance(...
action_typeN( ...
# no else statement
Ouch.. someone must have skipped his/her OO class...

Dec 22 '06 #8
George Sakkis wrote:
John Machin wrote:
Bruno Desthuilliers wrote:
<my humble opinion>
Python is dynamic, and fighting against the language is IMHO a really
bad idea. The only places where theres a real need for this kind of
stuff are when dealing with the "outside world" (IOW : inputs and
outputs). And then packages like formencode can do much more than mere
type-checking
</my humble opinion>
Agreed. The worst case I have seen:

An elaborate decorator (similar to the OP's) laboriously checks arg
types. That's IMHO not "consenting adults" territory. But it gets a
whole lot worse when it's applied to a method whose body is like this:

if isinstance(....
action_for_type 1(...
# big snip
elif isinstance(...
action_typeN( ...
# no else statement

Ouch.. someone must have skipped his/her OO class...
Quite possibly :-) but that's not the problem here.

The method in question might be called say emit_generic(se lf,
any_type_of obj) and so one bunch of isinstance calls is actually
needed, but not two bunches. So: lose the decorator and add an else and
a raise at the end.

There is a secondary problem: annoying the crap out of callers who
often know what type they have and want an emit_real which would take
an int, a long, or a float and an emit_strg and ... (yes, almost all
the possible types are that simple) which wouldn't go through even one
chain of isinstance calls.

Dec 22 '06 #9
"John Machin" <sj******@lexic on.netwrote:
if isinstance(....
action_for_type 1(...
# big snip
elif isinstance(...
action_typeN( ...
# no else statement

Ouch.. someone must have skipped his/her OO class...

Quite possibly :-) but that's not the problem here.

The method in question might be called say emit_generic(se lf,
any_type_of obj) and so one bunch of isinstance calls is actually
needed, but not two bunches. So: lose the decorator and add an else and
a raise at the end.

There is a secondary problem: annoying the crap out of callers who
often know what type they have and want an emit_real which would take
an int, a long, or a float and an emit_strg and ... (yes, almost all
the possible types are that simple) which wouldn't go through even one
chain of isinstance calls.
I think the point that was being made was that the method's body should be
something like:

actions[type(arg)](...)

which not only avoids all of the isinstance calls but also the else and the
raise at the end.
Dec 22 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

24
2049
by: Steven Bethard | last post by:
I think one of the biggest reasons we're having such problems coming to any agreement on decorator syntax is that each proposal makes a number of syntax decisions, not just one. For decorators, I see the following decisions that must be made: 1) Indicator Proposals differ on how some sort of indicator of "decoratorhood" is use. These include: * none (e.g. just the list, as in the "list-after-def" suggestion) * the '@' character
37
2591
by: Bengt Richter | last post by:
ISTM that @limited_expression_producing_function @another def func(): pass is syntactic sugar for creating a hidden list of functions. (Using '|' in place of '@' doesn't change the picture much (except for people whose tools depend on '@' ;-)). I.e., (not having the source or time to delve) the apparent semantics of the above is something roughly like
7
1579
by: Steven Bethard | last post by:
So here's the state of the decorator debate as I see it: *** Location GvR pretty strongly wants decorators before the function: http://mail.python.org/pipermail/python-dev/2004-August/047112.html http://mail.python.org/pipermail/python-dev/2004-August/047279.html
30
2489
by: Ron_Adam | last post by:
I was having some difficulty figuring out just what was going on with decorators. So after a considerable amount of experimenting I was able to take one apart in a way. It required me to take a closer look at function def's and call's, which is something I tend to take for granted. I'm not sure this is 100%, or if there are other ways to view it, but it seems to make sense when viewed this way. Is there a way to do this same thing...
22
2221
by: Ron_Adam | last post by:
Hi, Thanks again for all the helping me understand the details of decorators. I put together a class to create decorators that could make them a lot easier to use. It still has a few glitches in it that needs to be addressed. (1) The test for the 'function' object needs to not test for a string but an object type instead.
6
1392
by: Michele Simionato | last post by:
could ildg wrote: > I think decorator is a function which return a function, is this right? > e.g. The decorator below if from http://www.python.org/peps/pep-0318.html#id1. > > def accepts(*types): > def check_accepts(f): > assert len(types) == f.func_code.co_argcount
2
1491
by: lcaamano | last post by:
We have a tracing decorator that automatically logs enter/exits to/from functions and methods and it also figures out by itself the function call arguments values and the class or module the function/method is defined on. Finding the name of the class where the method we just entered was defined in is a bit tricky. Here's a snippet of the test code: class Base: @tracelevel(1)
4
1336
by: Gerardo Herzig | last post by:
Hi all. Im reading the Gido's aproach using decorators at http://www.artima.com/weblogs/viewpost.jsp?thread=101605 It looks good to me, but the examples shows the functionality using functions. Now, when i try to give this decorator into a method, if i try the class test(object): @multimethod(...) def met(self, ...):
4
2467
by: thomas.karolski | last post by:
Hi, I would like to create a Decorator metaclass, which automatically turns a class which inherits from the "Decorator" type into a decorator. A decorator in this case, is simply a class which has all of its decorator implementation inside a decorator() method. Every other attribute access is being proxied to decorator().getParent(). Here's my attempt: -------------------------------------------------------
0
8423
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
8290
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
6749
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
5889
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5446
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
3913
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
3960
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2438
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
0
1274
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.