Decorators not worth the effort
Jean-Michel Pichavant
jeanmichel at sequans.com
Fri Sep 14 09:22:26 EDT 2012
----- Original Message -----
> Jean-Michel Pichavant <jeanmichel at sequans.com> wrote:
>
> > I wrote the following one, used to decorate any function that
> > access
> > an equipment, it raises an exception when the timeout expires. The
> > timeout is adapted to the platform, ASIC of FPGA so people don't
> > need
> > to specify everytime one timeout per platform.
> >
> > In the end it would replace
> >
> > def boot(self, timeout=15):
> > if FPGA:
> > self.sendCmd("bootMe", timeout=timeout*3)
> > else:
> > self.sendCmd("bootMe", timeout=timeout)
> >
> > with
> >
> > @timeout(15)
> > def boot(self, timeout=None):
> > self.sendCmd("bootMe", timeout)
> >
> > I wrote a nice documentation with sphinx to explain this, how to
> > use
> > it, how it can improve code. After spending hours on the decorator
> > +
> > doc, feedback from my colleagues : What the F... !!
> >
>
> I'd agree with your colleagues. How are you going to ensure that all
> relevant functions are decorated and yet no decorated function ever
> calls another decorated one?
>
> From the code you posted it would seem appropriate that the
> adjustment
> of the timeout parameter happen in the `sendCmd()` method itself and
> nowhere else. Alternatively use named values for different categories
> of
> timeouts and adjust them on startup so instead of a default of
> `timeout=
> 15` you would have a default `timeout=MEDIUM_TIMEOUT` or whatever
> name
> is appropriate.
>
> --
> Duncan Booth http://kupuguy.blogspot.com
> --
> http://mail.python.org/mailman/listinfo/python-list
All functions set different timeout values, I cannot use a DEFAULT_VALUE.
All functions are design in the same way:
def doSomeAction(self, timeout):
preprocess()
self.sendCmd('relatedAction', timeout) # send the command to the device CLI interface
postprocess()
Ultimately, the goal is to have something like
@timeout(2)
def doAction1
@timeout(4)
def doAction2
@timeout(12)
def doAction3
and so on... (1 second is important, because there's a platform I remove from my example, didn't want to advertise publicly tech used by the company, that runs 1000 times slower)
Additionally, the multiple check I run within the decorator is for consistency check and argument checking. I though it was a good idea because our python engine is used by a dozen of engineers to control equipment, and any misuse of this new decorator would lead to badly configured timeouts with heavy consequences on the test sessions. Sometimes a RTFM is not enough, when you need to make this work, you slip on your Batman costume like Steven suggested, and you save the day (or so I though :) ) by raising nice exceptions about missing keyword argument.
But let's forget about my poor example, I end up describing my life which is pretty pointless.
Here's Steven example:
# Untested!
def timeout(t=15):
# Decorator factory. Return a decorator to actually do the work.
if FPGA:
t *= 3
def decorator(func):
@functools.wraps(func)
def inner(self, timeout):
self.sendCmd("bootMe", timeout=t)
return inner
return decorator
I can assure you, that for some python users, it's is not easy to understand what it does, this function returning a function which returns another (wrapped) function. It requires some effort.
JM
More information about the Python-list
mailing list