Is it possible to get string from function?

Peter Otten __peter__ at web.de
Thu Jan 16 03:52:57 EST 2014


Roy Smith wrote:

> I realize the subject line is kind of meaningless, so let me explain :-)
> 
> I've got some unit tests that look like:
> 
> class Foo(TestCase):
>   def test_t1(self):
>     RECEIPT = "some string"
> 
>   def test_t2(self):
>     RECEIPT = "some other string"
> 
>   def test_t3(self):
>     RECEIPT = "yet a third string"
> 
> and so on.  It's important that the strings be mutually unique.  In the
> example above, it's trivial to look at them and observe that they're all
> different, but in real life, the strings are about 2500 characters long,
> hex-encoded.  It even turns out that a couple of the strings are
> identical in the first 1000 or so characters, so it's not trivial to do
> by visual inspection.
> 
> So, I figured I would write a meta-test, which used introspection to
> find all the methods in the class, extract the strings from them (they
> are all assigned to a variable named RECEIPT), and check to make sure
> they're all different.
> 
> Is it possible to do that?  It is straight-forward using the inspect
> module to discover the methods, but I don't see any way to find what
> strings are assigned to a variable with a given name.  Of course, that
> assignment doesn't even happen until the function is executed, so
> perhaps what I want just isn't possible?
> 
> It turns out, I solved the problem with more mundane tools:
> 
> grep 'RECEIPT = ' test.py | sort | uniq -c
> 
> and I could have also solved the problem by putting all the strings in a
> dict and having the functions pull them out of there.  But, I'm still
> interested in exploring if there is any way to do this with
> introspection, as an academic exercise.

Instead of using introspection you could make it explicit with a decorator:

$ cat unique_receipt.py 
import functools
import sys
import unittest

_receipts = {}
def unique_receipt(receipt):
    def deco(f):
        if receipt in _receipts:
            raise ValueError(
                "Duplicate receipt {!r} in \n    {} and \n    {}".format(
                    receipt, _receipts[receipt], f))
        _receipts[receipt] = f
        @functools.wraps(f)
        def g(self):
            return f(self, receipt)
        return g
    return deco

class Foo(unittest.TestCase):
    @unique_receipt("foo")
    def test_t1(self, RECEIPT):
        pass

    @unique_receipt("bar")
    def test_t2(self, RECEIPT):
        pass

    @unique_receipt("foo")
    def test_t3(self, RECEIPT):
        pass

if __name__ == "__main__":
    unittest.main()
$ python unique_receipt.py 
Traceback (most recent call last):
  File "unique_receipt.py", line 19, in <module>
    class Foo(unittest.TestCase):
  File "unique_receipt.py", line 28, in Foo
    @unique_receipt("foo")
  File "unique_receipt.py", line 11, in deco
    receipt, _receipts[receipt], f))
ValueError: Duplicate receipt 'foo' in 
    <function test_t1 at 0x7fc8714af5f0> and 
    <function test_t3 at 0x7fc8714af7d0>





More information about the Python-list mailing list