def SmartSet(self, obj, attr_name, new_attr):
    """Replace obj.attr_name with new_attr. This method is smart and works
       at the module, class, and instance level while preserving proper
       inheritance. It will not stub out C types however unless that has been
       explicitly allowed by the type.

       This method supports the case where attr_name is a staticmethod or a
       classmethod of obj.

       Notes:
      - If obj is an instance, then it is its class that will actually be
        stubbed. Note that the method Set() does not do that: if obj is
        an instance, it (and not its class) will be stubbed.
      - The stubbing is using the builtin getattr and setattr. So, the __get__
        and __set__ will be called when stubbing (TODO: A better idea would
        probably be to manipulate obj.__dict__ instead of getattr() and
        setattr()).

       Raises AttributeError if the attribute cannot be found.
    """
    if (inspect.ismodule(obj) or
        (not inspect.isclass(obj) and obj.__dict__.has_key(attr_name))):
      orig_obj = obj
      orig_attr = getattr(obj, attr_name)

    else:
      if not inspect.isclass(obj):
        mro = list(inspect.getmro(obj.__class__))
      else:
        mro = list(inspect.getmro(obj))

      mro.reverse()

      orig_attr = None

      for cls in mro:
        try:
          orig_obj = cls
          orig_attr = getattr(obj, attr_name)
        except __HOLE__:
          continue

    if orig_attr is None:
      raise AttributeError("Attribute not found.")

    # Calling getattr() on a staticmethod transforms it to a 'normal' function.
    # We need to ensure that we put it back as a staticmethod.
    old_attribute = obj.__dict__.get(attr_name)
    if old_attribute is not None and isinstance(old_attribute, staticmethod):
      orig_attr = staticmethod(orig_attr)

    self.stubs.append((orig_obj, attr_name, orig_attr))
    setattr(orig_obj, attr_name, new_attr)
dataset/ETHPy150Open AppScale/appscale/AppServer/lib/mox/stubout.py/StubOutForTesting.SmartSet