1

Trying to create a decorator for a few methods in a class. The decorator works as expected without parameters:

class OtherMenu:                                                                                                        
    current_page = 'algo'                                                                                               
                          
                                                                                   
class MenuSidebarWebScreen(OtherMenu):                                                                                  
                                                                                                                     
    def decorator(foo):                                                                                                 
        def magic(self):                                                                                                
            import ipdb                                                                                                 
            ipdb.set_trace()                                                                                            
            print("start magic")                                                                                        
            foo(self)                                                                                                   
            print("end magic")                                                                                          
        return magic                                                                                                    
                                                                                                                     
    @decorator                                                                                                          
    def go_to_home_page(self):                                                                                          
        if self.current_page == "Home":                                                                                 
            print(f'Already in the {self.current_page}, skipping menu interaction.')                                    
            return                                                                                                      
        # Do awesome stuff over here
        self.current_page = "Home"
>>> from features.steps.web_ui.menu.menu_sidebar_web_screen import MenuSidebarWebScreen
>>> menu = MenuSidebarWebScreen()
>>> menu.go_to_home_page()
ipdb> foo
<function MenuSidebarWebScreen.go_to_home_page at 0x10dbd1280>
ipdb> self
<features.steps.web_ui.menu.menu_sidebar_web_screen.MenuSidebarWebScreen object at 0x10c85e280>
ipdb>

But when I add a parameter to the decorator, like this

        @decorator("Something")  <----------- Added a parameter to the decorator
        def go_to_home_page(self):                                                                                          
            if self.current_page == "Home":                                                                                 

the behavior changes. First of all, the decorator method is called as soon as I import the class (instead of calling the class method). Also the values from the pdb itself change to:

>>> from features.steps.web_ui.menu.menu_sidebar_web_screen import MenuSidebarWebScreen
ipdb> self
<function MenuSidebarWebScreen.go_to_home_page at 0x10a07c310>
ipdb> foo
'Something'

What is the proper way to use the class inside the decorator? I was hoping to use these parts of the code to the decorator itself:

            if self.current_page == "Home":                                                                                 
                print(f'Already in the {self.current_page}, skipping menu interaction.')                                    
                return                                                                                                      
            ... ------> Everything else, that will remain on the go_to_home_page method
            self.current_page = "Home"
Vini.g.fer
  • 11,639
  • 16
  • 61
  • 90
  • Could you give a [mre] of what _doesn't_ work? Also _"the decorator method is called as soon as I import the class"_ is surely the expected behaviour in either case - a decorator is called with the function/method it's decorating. – jonrsharpe Dec 03 '21 at 16:29
  • Added more details with the Python interpreter. Could you have a look now please? – Vini.g.fer Dec 03 '21 at 17:12
  • And do you actually change the decorator to account for the fact that you're now expecting it to be a decorator _factory_? – jonrsharpe Dec 03 '21 at 17:15
  • 2
    I suspect this is a dupe of https://stackoverflow.com/q/5929107/3001761 – jonrsharpe Dec 03 '21 at 17:58

0 Answers0