2

I've found way to have decorator in class, to have decorator with args, to decorate function with args. But I can't make all of it work together. How can I make this work ?

class Printer():
    """
    Print thing with my ESCPOS printer
    """
    def text(self, text):
        with open('/dev/usb/lp0', 'wb') as lp0:
            lp0.write(text.encode('cp437'))
            lp0.write(b'\n')
    def command(self, command):
        with open('/dev/usb/lp0', 'wb') as lp0:
            lp0.write(command)
            lp0.write(b'\n')
    def style(command_before, command_after):
        """
        Send a command before and a command after
        """
        def decorator(func):
            def wrapper(self, text):
                print(self)
                print(text)
                self.command(command_before)
                func(text)
                self.command(command_after)
            return wrapper
        return decorator
    @style((b'\x1D\x42\x31'), (b'\x1D\x42\x32')) #print white on black
    @style((b'\x1D\x21\x34'), (b'\x1D\y21\x00')) #print bigger
    def title(self, title_text):
        self.text(title_text)

then I could use it that way:

p = Printer()
p.title('This is an awesome TITLE!!')

This give me a "TypeError: wrapper() missing 1 required positional argument: 'text'"

But I just fail to get it :/

3
  • 1
    is style() supposed to be a static method? You aren't passing in self Commented Jan 11, 2017 at 12:20
  • style only appears to be intended to be used inside the class definition; what the metaclass does with it once the class is defined doesn't appear to matter. Commented Jan 11, 2017 at 12:27
  • 1
    @chepner: Ah. I think I get it. :) Because style is used as a decorator while the class is being defined it's behaving like a normal (unbound) function, not a method, so it doesn't take a self arg. And that means we could move the definition of style outside of the class Printer(): definition & it will still work correctly. Commented Jan 11, 2017 at 12:34

2 Answers 2

3

func() in your decorator is still an unbound function. You need to bind it explicitly or pass in self explicitly:

# bind it to self
func.__get__(self)(text)

# or simply pass in self directly
func(self, text)
Sign up to request clarification or add additional context in comments.

Comments

2

Your call to func needs to read func(self, text). The reason is that in this case func is not yet a bound method to an instance.

That is not possible at the time the class is created. There is no instance that you could bound it to. So func in your wrapper function is just a plain function and hence needs the same arguments as you defined it with

def title(self, title_text)
    ...

I changed the example like this

class Printer():
    """
    Print thing with my ESCPOS printer
    """
    def text(self, text):
#         with open('/dev/usb/lp0', 'wb') as lp0:
#             lp0.write(text.encode('cp437'))
#             lp0.write(b'\n')
        print('Text', text)

    def command(self, command):
#         with open('/dev/usb/lp0', 'wb') as lp0:
#             lp0.write(command)
#             lp0.write(b'\n')
        print('Command', command)

    def style(command_before, command_after):
        """
        Send a command before and a command after
        """
        def decorator(func):
            def wrapper(self, text):
#                 print(self)
#                 print(text)
                print('type of func', type(func))  # see that it is not bound
                self.command(command_before)
                func(self, text)  # <-- use (self, ...)
                self.command(command_after)
            return wrapper
        return decorator

    @style((b'\x1D\x42\x31'), (b'\x1D\x42\x32')) #print white on black
    @style((b'\x1D\x21\x34'), (b'\x1D\y21\x00')) #print bigger
    def title(self, title_text):
        self.text(title_text)

2 Comments

@PM 2Ring Thanks for the hint. I should have look more carefully.
Exactly the answer I was lookin for :) and the explaination I was lookin for

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.