docs: def undecorated(o):
      """Remove all decorators from a function, method or class"""
      # class decorator
      if type(o) is type:
          return o
  
      try:
          # python2
          closure = o.func_closure
      except AttributeError:
          pass
  
      try:
          # python3
          closure = o.__closure__
      except AttributeError:
          return
  
      if closure:
          for cell in closure:
              # avoid infinite recursion
              if cell.cell_contents is o:
                  continue
  
              # check if the contents looks like a decorator; in that case
              # we need to go one level down into the dream, otherwise it
              # might just be a different closed-over variable, which we
              # can ignore.
  
              # Note: this favors supporting decorators defined without
              # @wraps to the detriment of function/method/class closures
              if looks_like_a_decorator(cell.cell_contents):
                  undecd = undecorated(cell.cell_contents)
                  if undecd:
                      return undecd
          else:
              return o
      else:
          return o