Search code examples
pythonpytestfunctools

testing undecorated function with .__wrapped__ gives error "requires 1 more positional argument"


I have looked for this on the forum but i could find anything precisely dealing with functool wrapped...

I have a class with a function copyfile and a decorator fileprocessing defined as :

class Sync():
    ...
    def fileprocessing(func):
        "decorator for copyfile methods"
        @functools.wraps(func)
        def wrapped_f(*args):
            ...#some code invoking copyfile
        return wrapped_f

    @fileprocessing
    def copyfile(self,src, dst, file):
        "try copying with shutil file in src folder to dst folder, otherwise with python"
        try:
            shutil.copy2(f'{src}/{file}',f'{dst}/{file}', follow_symlinks=False)
        except Exception as err:
            print(err)
            self.pythoncopyfile(f'{src}/{file}',f'{dst}/{file}')

I am trying to test this function with pytest and it works fine when it is decorated. However, i want to test the undecorated function.

I put in my test_file.py :

def test_undecorated_copyfile():
    sync=Sync()
    for file in range(3):  
        sync.copyfile.__wrapped__('source_folder', 'dest_folder', f'{file}.txt')

And when i run pytest, it throws me "TypeError: copyfile() missing 1 required positional argument: 'file' "

So i guess this has something to do with how to handle "self" in the copyfile arguments, but i dont know where to begin with to understand what .__wrapped__ is doing wrong

I tried to look on the forum but all i get is how to undecorate a function (with ._wrapped_ ), how to deal with self in normal situations.
I dont know how to deal with this error and which objects or methods to use to investigate


Solution

  • So i guess this has something to do with how to handle "self" in the copyfile arguments, but i dont know where to begin with to understand what .__wrapped__ is doing wrong

    You're exactly right.

    The .__wrapped__ attribute is an (unbound) function here (not a method)

    print(sync.copyfile.__wrapped__)
    #  prints <function Sync.copyfile ...>, 
    #  not    <bound method Sync.copyfile of <__main__.Sync object ...>
    

    and therefore needs a "self" argument supplied explicitly, e.g.:

    # Change
    sync.copyfile.__wrapped__('source_folder', 'dest_folder', f'{file}.txt')
    
    # to                      ↓↓↓↓
    sync.copyfile.__wrapped__(sync, 'source_folder', 'dest_folder', f'{file}.txt')