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