-1

I have the following code:

def test(testFunc):
    def runTest(*args, **kwargs):
        testFunc(*args, **kwargs)
    return runTest


@test
def func1():
    pass

@test
def func2():
    pass

tests = [func1, func2]

def RunTest():
   testList = [x.__name__ for x in tests ]
   print(testList)

Running above code prints [runTest, runTest] which is the name of the decorator. Any idea why this happens and how to fix it?

Nikhil
  • 2,168
  • 6
  • 33
  • 51
  • You *must* provide a [mcve]. What is `cleanup`? In any case, why do you *expect* it to print the name of the original function? Do you understand that your decorator returns another function, `runTest`? – juanpa.arrivillaga Mar 02 '21 at 07:04
  • @juanpa All the more surprising that it says “test” then… – deceze Mar 02 '21 at 07:07
  • fixed some of the errors in my question. Thanks for pointing it out – Nikhil Mar 02 '21 at 07:11

1 Answers1

2

This is one of the reasons why functools.wraps exists

By adding @wraps(testFunc) to your runTest function the names of the original function is retained. It essentially does something like this:

runTest.__name__ = testFunc.__name__

before returning runTest

This doesn't happen in your example because vanilla decorators are simply:

func1 = test(func1)

(wraps also copies any docstring from the wrapped function)

Just add @wraps to your inner function

def test(testFunc):
    @wraps(testFunc)
    def runTest(*args, **kwargs):
        testFunc(*args, **kwargs)
    return runTest

And you should get:

['func1', 'func2']

rdas
  • 20,604
  • 6
  • 33
  • 46