0

I am try to use a decorator to do some debugging and learn about decorators and I do not understand why I am getting this error:

  File "/Users/red/PycharmProjects/general_purpose_object_factory/music.py", line 26, in __call__
    self._instance = SpotifyService(access_code)
TypeError: wrapper() takes 0 positional arguments but 2 were given

Process finished with exit code 

Here is my code:

decorators.py

def debug_printer(func):
    def wrapper():
        print("Hello")
        func()
    return wrapper

music.py

import object_factory
from decorators import debug_printer

class MusicServiceProvider(object_factory.ObjectFactory):
    def get(self, service_id, **kwargs):
        return self.create(service_id, **kwargs)

class SpotifyService:
    @debug_printer
    def __init__(self, access_code):
        self._access_code = access_code

    def test_connection(self):
        print(f'Accessing Spotify with {self._access_code}')


class SpotifyServiceBuilder:
    def __init__(self):
        print(f"{__class__.__name__}")
        self._instance = None

    def __call__(self, spotify_client_key, spotify_client_secret, **_ignored):
        if not self._instance:
            access_code = self.authorize(
                spotify_client_key, spotify_client_secret)
            self._instance = SpotifyService(access_code)  # <<< LINE 26. !!!!!!
        return self._instance

    def authorize(self, key, secret):
        return 'SPOTIFY_ACCESS_CODE'

Can someone please explain what I am doing wrong?

Red Cricket
  • 9,762
  • 21
  • 81
  • 166
  • 1
    What part of `TypeError: wrapper() takes 0 positional arguments but 2 were given` is unclear? The decorator returns the locally-created `wrapper`; it was defined like `def wrapper():`, so why is it surprising that it doesn't accept any arguments? So, the next question is: *should* it accept arguments? (Yes, because it's decorating something that accepts arguments, and it is expected that the decorated result will be used with the same signature.) Therefore.... – Karl Knechtel Jul 31 '22 at 03:20
  • I'm voting to close as a typo because it's not clear to me why the logic would be troublesome *for someone who already knows what decorators are and the syntax to write them*. If there's some more specific reason you expected this to work, and existing references such as https://stackoverflow.com/questions/739654/ (definitely not a duplicate, but the standard reference material for decorators on Stack Overflow) don't resolve the issue, please try to ask more specifically. – Karl Knechtel Jul 31 '22 at 03:22
  • My usual advice: "what am I doing wrong?"/"why doesn't this work?" etc. is very often the wrong framing. Instead, try to convince us of *why it should* work, and exactly how. (Oh, and I shouldn't have to point an 11-year veteran of the site at this, but please read [mre].) – Karl Knechtel Jul 31 '22 at 03:23
  • WELL EXCUSE ME! – Red Cricket Jul 31 '22 at 03:28

1 Answers1

1

ok I had to change my decorator to this ...

def debug_printer(func):
    def wrapper(*args, **kwargs):
        print(f"Calling {func.__qualname__}({args}, {kwargs})")
        return func(*args, **kwargs)
    return wrapper
Red Cricket
  • 9,762
  • 21
  • 81
  • 166