docs: def _create_extension(o, otype, fqdn, pmodule):
      """Creates an extension object to represent `o` that can have attributes
      set, but which behaves identically to the given object.
  
      Args:
          o: object to create an extension for; no checks are performed to see if
            extension is actually required.
          otype (str): object types; one of ["classes", "functions", "methods",
            "modules"].
          fqdn (str): fully qualified name of the package that the object belongs
            to.
          pmodule: the parent module (or class) that `o` belongs to; used for setting
            the special __module__ attribute.
      """
      import types
      xdict = {"__acornext__": o,
               "__doc__": o.__doc__}
  
      if otype == "classes":
          classname = o.__name__
          try:
              if fqdn in _explicit_subclasses:
                  xclass = eval(_explicit_subclasses[fqdn])
                  xclass.__acornext__ = o
              else:
                  xclass = type(classname, (o, ), xdict)
              xclass.__module__ = o.__module__
              return xclass
          except TypeError:
              #This happens when a class is final, meaning that it is not allowed
              #to be subclassed.
              _final_objs.append(id(o))
              return o
      elif (otype in ["functions", "descriptors", "unknowns"] or
            (otype == "builtins" and (isinstance(o, types.BuiltinFunctionType) or
                                      isinstance(o, types.BuiltinMethodType)))):
          #The unknowns type is for objects that don't match any of the
          #inspect.is* function calls, but still have a __call__ method (such as
          #the numpy.ufunc class instances). These can still be wrapped by another
          #function.
          def xwrapper(*args, **kwargs):
              try:
                  return o(*args, **kwargs)
              except:
                  #see issue #4.
                  targs = list(map(type, args))
                  kargs = list(kwargs.keys())
                  msg.err("xwrapper: {}({}, {})".format(o, targs, kargs), 2)
                  pass
              
          #Set the docstring and original object attributes.
          for attr, val in xdict.items():
              setattr(xwrapper, attr, val)
              
          #We want to get the members dictionary. For classes, using
          #:meth:`inspect.getmembers` produces stack overflow errors. Instead, we
          #reference the __dict__ directly. However, for built-in methods and
          #functions, there is no __dict__, so we use `inspect.getmembers`.
          failed = False
          setattr(xwrapper, "__getattribute__", _safe_getattr(xwrapper))
  
          #We want the new function to be identical to the old except that
          #it's __call__ method, which we overrode above.
          failed = not _update_attrs(xwrapper, o, ["__call__"])
  
          if otype in ["descriptors", "unknowns"] and inspect.ismodule(pmodule):
              if hasattr(o, "__objclass__"): # pragma: no cover
                  setattr(xwrapper, "__module__", pmodule.__name__)
              elif hasattr(o, "__class__") and o.__class__ is not None:
                  setattr(xwrapper, "__module__", pmodule.__name__)
  
          if not failed:
              return xwrapper