docs: def inject_func_as_method(self, func, method_name=None, class_=None,
                            allow_override=False, allow_main=False,
                            verbose=True, override=None, force=False):
      """ Injects a function into an object as a method
  
      Wraps func as a bound method of self. Then injects func into self
      It is preferable to use make_class_method_decorator and inject_instance
  
      Args:
         self (object): class instance
         func : some function whos first arugment is a class instance
         method_name (str) : default=func.__name__, if specified renames the method
         class_ (type) : if func is an unbound method of this class
  
  
      References:
          http://stackoverflow.com/questions/1015307/python-bind-an-unbound-method
      """
      if override is not None:
          # TODO depcirate allow_override
          allow_override = override
      if method_name is None:
          method_name = get_funcname(func)
      if force:
          allow_override = True
          allow_main = True
      old_method = getattr(self, method_name, None)
      # Bind function to the class instance
      #new_method = types.MethodType(func, self, self.__class__)
      new_method = func.__get__(self, self.__class__)
      #new_method = profile(func.__get__(self, self.__class__))
  
      if old_method is not None:
          old_im_func = get_method_func(old_method)
          new_im_func = get_method_func(new_method)
          if not allow_main and old_im_func is not None and (
                  get_funcglobals(old_im_func)['__name__'] != '__main__' and
                  get_funcglobals(new_im_func)['__name__'] == '__main__'):
              if True or VERBOSE_CLASS:
                  print('[util_class] skipping re-inject of %r from __main__' % method_name)
              return
          if old_method is new_method or old_im_func is new_im_func:
              #if verbose and util_arg.NOT_QUIET:
              #    print('WARNING: Skipping injecting the same function twice: %r' % new_method)
                  #print('WARNING: Injecting the same function twice: %r' % new_method)
              return
          elif allow_override is False:
              raise AssertionError(
                  'Overrides are not allowed. Already have method_name=%r' %
                  (method_name))
          elif allow_override == 'warn':
              print(
                  'WARNING: Overrides are not allowed. Already have method_name=%r. Skipping' %
                  (method_name))
              return
          elif allow_override == 'override+warn':
              #import utool as ut
              #ut.embed()
              print('WARNING: Overrides are allowed, but dangerous. method_name=%r.' %
                    (method_name))
              print('old_method = %r, im_func=%s' % (old_method, str(old_im_func)))
              print('new_method = %r, im_func=%s' % (new_method, str(new_im_func)))
              print(get_funcglobals(old_im_func)['__name__'])
              print(get_funcglobals(new_im_func)['__name__'])
          # TODO: does this actually decrement the refcount enough?
          del old_method
      setattr(self, method_name, new_method)