docs: def patch_object(obj, attr_name, patched_value):
      """Patches an object and returns an instance of :class:`fudge.patcher.PatchHandler` for later restoration.
  
      Note that if *obj* is not an object but a path to a module then it will be imported.
  
      You may want to use a more convenient wrapper :func:`with_patched_object` or :func:`patched_context`
  
      Example::
  
          >>> from fudge import patch_object
          >>> class Session:
          ...     state = 'clean'
          ...
          >>> patched_session = patch_object(Session, "state", "dirty")
          >>> Session.state
          'dirty'
          >>> patched_session.restore()
          >>> Session.state
          'clean'
  
      Here is another example showing how to patch multiple objects at once::
  
          >>> class Session:
          ...     state = 'clean'
          ...
          >>> class config:
          ...     session_strategy = 'database'
          ...
          >>> patches = [
          ...     patch_object(config, "session_strategy", "filesystem"),
          ...     patch_object(Session, "state", "dirty")
          ... ]
          >>> try:
          ...     # your app under test would run here ...
          ...     print "(while patched)"
          ...     print "config.session_strategy=%r" % config.session_strategy
          ...     print "Session.state=%r" % Session.state
          ... finally:
          ...     for p in patches:
          ...         p.restore()
          ...     print "(patches restored)"
          (while patched)
          config.session_strategy='filesystem'
          Session.state='dirty'
          (patches restored)
          >>> config.session_strategy
          'database'
          >>> Session.state
          'clean'
  
      """
      if isinstance(obj, (str, unicode)):
          obj_path = adjusted_path = obj
          done = False
          exc = None
          at_top_level = False
          while not done:
              try:
                  obj = __import__(adjusted_path)
                  done = True
              except ImportError:
                  # Handle paths that traveerse object attributes.
                  # Such as: smtplib.SMTP.connect
                  #          smtplib <- module to import
                  adjusted_path = adjusted_path.rsplit('.', 1)[0]
                  if not exc:
                      exc = sys.exc_info()
                  if at_top_level:
                      # We're at the top level module and it doesn't exist.
                      # Raise the first exception since it will make more sense:
                      etype, val, tb = exc
                      raise etype, val, tb
                  if not adjusted_path.count('.'):
                      at_top_level = True
          for part in obj_path.split('.')[1:]:
              obj = getattr(obj, part)
  
      handle = PatchHandler(obj, attr_name)
      handle.patch(patched_value)
      return handle