Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #56644 > unrolled thread

Re: Skipping decorators in unit tests

Started byCameron Simpson <cs@zip.com.au>
First post2013-10-11 15:36 +1100
Last post2013-10-11 17:40 +1100
Articles 3 — 2 participants

Back to article view | Back to comp.lang.python

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: Skipping decorators in unit tests Cameron Simpson <cs@zip.com.au> - 2013-10-11 15:36 +1100
    Re: Skipping decorators in unit tests Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-10-11 05:51 +0000
      Re: Skipping decorators in unit tests Cameron Simpson <cs@zip.com.au> - 2013-10-11 17:40 +1100

#56644 — Re: Skipping decorators in unit tests

FromCameron Simpson <cs@zip.com.au>
Date2013-10-11 15:36 +1100
SubjectRe: Skipping decorators in unit tests
Message-ID<mailman.983.1381466200.18130.python-list@python.org>
On 11Oct2013 14:42, Ben Finney <ben+python@benfinney.id.au> wrote:
> Cameron Simpson <cs@zip.com.au> writes:
> > On 11Oct2013 02:55, Steven D'Aprano <steve+comp.lang.python@pearwood.info> wrote:
> > > def undecorate(f):
> > >     """Return the undecorated inner function from function f."""
> > >     return f.func_closure[0].cell_contents
> >
> > Whereas this feels like black magic. Is this portable to any decorated
> > function? If so, I'd have hoped it was in the stdlib. If not: black
> > magic.
> 
> What would you expect? The purpose of decorating functions is to do
> magic to make it appear as though the original function isn't there any
> more. Any technique to getting at that original function anyway is *of
> course* going to look like black magic at the implementation level.

Sigh. Yes of course. It is no uglier than walking a frame stack etc.

But is it reliable? Will it work on any decorated function?

If so, fine, and I'd be happy to squirrel it away as a useful
standard incantation for something.

If not, then it's nasty only-mostly-reliable magic and I either
want little to do with it, OR I want to know its specific limitations
so I know when to use it and when not.
-- 
Cameron Simpson <cs@zip.com.au>

But pessimism IS realism!       - D.L.Bahr

[toc] | [next] | [standalone]


#56645

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2013-10-11 05:51 +0000
Message-ID<525791e2$0$29984$c3e8da3$5496439d@news.astraweb.com>
In reply to#56644
On Fri, 11 Oct 2013 15:36:29 +1100, Cameron Simpson wrote:

> But is it reliable? Will it work on any decorated function?

*Any* decorated function? No, of course not, since decorators can do 
anything they like:

def decorate(func):
    return lambda *args: "Surprise!"

@decorate
def something_useful(x, y):
    return x+y


They don't even have to return a function. Or the function being 
decorated can end up in a different cell:

def factory(x, y):
    def decorator(func):
        def inner(*args):
            _ = (x, y)  # pretend x and y are useful
            return func(*args)
        return inner
    return decorator


@factory(lambda: None, 42)
def func(a):
    return a



py> func.func_closure[0].cell_contents
42
py> func.func_closure[1].cell_contents
<function <lambda> at 0xb7c4609c>
py> func.func_closure[2].cell_contents
<function func at 0xb7c4617c>


So consider this a *cooperative* undecorator. It can only undecorate 
things that are decorated the way you expect them to be decorated. 


-- 
Steven

[toc] | [prev] | [next] | [standalone]


#56653

FromCameron Simpson <cs@zip.com.au>
Date2013-10-11 17:40 +1100
Message-ID<mailman.987.1381473621.18130.python-list@python.org>
In reply to#56645
On 11Oct2013 05:51, Steven D'Aprano <steve+comp.lang.python@pearwood.info> wrote:
> On Fri, 11 Oct 2013 15:36:29 +1100, Cameron Simpson wrote:
> > But is it reliable? Will it work on any decorated function?
> 
> *Any* decorated function? No, of course not, since decorators can do 
> anything they like: [... examples ...]

That was what I thought; I was pretty sure I could quite reasonably
write all sorts of decorators this wouldn't work with.

> So consider this a *cooperative* undecorator. It can only undecorate 
> things that are decorated the way you expect them to be decorated. 

Fine.

And that is why I wrote my example as I did; I'd rather expose the
inner function by name if it is to be tested rather than write a
somewhat opaque special function that relies on all my decorators
following the same internal scheme. I'd only have to forget in the
frenzy of writing some special decorator to have my tests break
(or, worse, test the wrong thing).

So, for me, _if_ I intend to test the inner function alone, it is
worth the trade off of an extra name to avoid any need for special
knowledge of the inner workings of the decorators.

Cheers,
-- 
Cameron Simpson <cs@zip.com.au>

A childproof cap is a Gordian knot to any adult who drinks.  ______ wrote
that he had seen the best minds of his generation destroyed by madness. I
have seen the best minds of mine go at a bottle of aspirin with a ball-peen
hammer. - P.J. O'Rourke

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web