cpburnz

Class decorator example

Oct 12th, 2012
126
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.38 KB | None | 0 0
  1. # coding: utf-8
  2. """
  3. This is an example using a class as a decorator.
  4. """
  5.  
  6. class logexcept(object):
  7.     """
  8.     There are 2 cases for using this decorator. The first is without a
  9.     call to @logexcept when decorating
  10.    
  11.     >>> @logexcept
  12.     >>> def myfunc(*args, **kw):
  13.     >>>     ...
  14.    
  15.     This is equivalent to:
  16.    
  17.     >>> def myfunc(*args, **kw):
  18.     >>>     ...
  19.     >>> myfunc = logexcept(myfunc)
  20.    
  21.     The second is when there s a call to @logexcept(...) when decorating
  22.     the function.
  23.    
  24.     >>> @logexcept(...)
  25.     >>> def myfunc(*args, **kw):
  26.     >>>     ...
  27.    
  28.     This is equivalent to:
  29.    
  30.     >>> def myfunc(*args, **kw):
  31.     >>>     ...
  32.     >>> mydec = logexcept(...)
  33.     >>> myfunc = mydec(myfunc)
  34.     >>> # OR: myfunc = logexcept(...)(myfunc)
  35.     """
  36.  
  37.     def __init__(self, *args, **kwargs):
  38.         if args and callable(args[0]):
  39.             '''
  40.             We are doing:
  41.        
  42.             >>> @logexcept
  43.             >>> def myfunc(...)
  44.             '''
  45.             self.func = args[0]
  46.            
  47.         else:
  48.             '''
  49.             We are doing:
  50.            
  51.             >>> @logexcept(...)
  52.             >>> def myfunc(...)
  53.            
  54.             So *args and **kwargs are the arguments passed to logexcept, and
  55.             myfunc will be passed in __call__
  56.             '''
  57.             self.func = None
  58.            
  59.     def __call__(self, *args, **kwargs):
  60.         if self.func:
  61.             '''
  62.             Since we have func, this means we can just pass these args to
  63.             myfunc because we're doing:
  64.            
  65.             >>> myfunc(...) # Call our wrapped function.
  66.             '''
  67.             return self.func(*args, **kwargs)
  68.            
  69.         else:
  70.             '''
  71.             Since we do not have func yet, this means we did:
  72.            
  73.             >>> @logexcept(...)
  74.             >>> def myfunc(...)
  75.            
  76.             And this __call__ is where we're really wrapping myfunc:
  77.            
  78.             >>> def myfunc(...):
  79.             >>>     ...
  80.             >>> mydec = logexcept(...) # <-- THIS WAS __init__
  81.             >>> myfunc = mydec(myfunc) # <-- RIGHT NOW IS __call__
  82.             '''
  83.             if not args or not callable(args[0]):
  84.                 raise TypeError("Did not get callable, got %r and %r." % (args, kwargs))
  85.            
  86.             self.func = args[0]
  87.             # The next time this is called, the first if statement will be ran.
  88.             # Make sure to return self so that when decorating with arguments,
  89.             # we actually get this wrapper instead of None.
  90.             return self
  91.            
  92.     def __get__(self, obj, type=None):
  93.         """
  94.         This is extra binding logic making self (an instance of logexcept) a
  95.         function descriptor so that decorating methods in classes work
  96.         properly (i.e., they get passed self or cls properly).
  97.         """
  98.         self.func = self.func.__get__(obj, type)
  99.         return self
Advertisement
Add Comment
Please, Sign In to add comment