docs: def getdoc(obj):
      """
      Return text documentation from an object. This comes in a form of
      dictionary with four keys:
  
      name:
        The name of the inspected object
      argspec:
        It's argspec
      note:
        A phrase describing the type of object (function or method) we are
        inspecting, and the module it belongs to.
      docstring:
        It's docstring
      """
      
      docstring = inspect.getdoc(obj) or inspect.getcomments(obj) or ''
      
      # Most of the time doc will only contain ascii characters, but there are
      # some docstrings that contain non-ascii characters. Not all source files
      # declare their encoding in the first line, so querying for that might not
      # yield anything, either. So assume the most commonly used
      # multi-byte file encoding (which also covers ascii). 
      try:
          docstring = to_text_string(docstring)
      except:
          pass
      
      # Doc dict keys
      doc = {'name': '',
             'argspec': '',
             'note': '',
             'docstring': docstring}
      
      if callable(obj):
          try:
              name = obj.__name__
          except AttributeError:
              doc['docstring'] = docstring
              return doc
          if inspect.ismethod(obj):
              imclass = get_meth_class(obj)
              if get_meth_class_inst(obj) is not None:
                  doc['note'] = 'Method of %s instance' \
                                % get_meth_class_inst(obj).__class__.__name__
              else:
                  doc['note'] = 'Unbound %s method' % imclass.__name__
              obj = get_meth_func(obj)
          elif hasattr(obj, '__module__'):
              doc['note'] = 'Function of %s module' % obj.__module__
          else:
              doc['note'] = 'Function'
          doc['name'] = obj.__name__
          if inspect.isfunction(obj):
              if PY2:
                  args, varargs, varkw, defaults = inspect.getargspec(obj)
                  doc['argspec'] = inspect.formatargspec(
                      args, varargs, varkw, defaults,
                      formatvalue=lambda o:'='+repr(o))
              else:
                  (args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults,
                   annotations) = inspect.getfullargspec(obj)
                  doc['argspec'] = inspect.formatargspec(
                      args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults,
                      annotations, formatvalue=lambda o:'='+repr(o))
              if name == '<lambda>':
                  doc['name'] = name + ' lambda '
                  doc['argspec'] = doc['argspec'][1:-1] # remove parentheses
          else:
              argspec = getargspecfromtext(doc['docstring'])
              if argspec:
                  doc['argspec'] = argspec
                  # Many scipy and numpy docstrings begin with a function
                  # signature on the first line. This ends up begin redundant
                  # when we are using title and argspec to create the
                  # rich text "Definition:" field. We'll carefully remove this
                  # redundancy but only under a strict set of conditions:
                  # Remove the starting charaters of the 'doc' portion *iff*
                  # the non-whitespace characters on the first line 
                  # match *exactly* the combined function title 
                  # and argspec we determined above.
                  signature = doc['name'] + doc['argspec']
                  docstring_blocks = doc['docstring'].split("\n\n")
                  first_block = docstring_blocks[0].strip()
                  if first_block == signature:
                      doc['docstring'] = doc['docstring'].replace(
                                                       signature, '', 1).lstrip()
              else:
                  doc['argspec'] = '(...)'
          
          # Remove self from argspec
          argspec = doc['argspec']
          doc['argspec'] = argspec.replace('(self)', '()').replace('(self, ', '(')
          
      return doc