content: from __future__ import division, absolute_import, print_function
  
  import sys, re, inspect, textwrap, pydoc
  import sphinx
  import collections
  from .docscrape import NumpyDocString, FunctionDoc, ClassDoc
  
  if sys.version_info[0] >= 3:
      sixu = lambda s: s
  else:
      sixu = lambda s: unicode(s, 'unicode_escape')
  
  
  class SphinxDocString(NumpyDocString):
      def __init__(self, docstring, config={}):
          NumpyDocString.__init__(self, docstring, config=config)
          self.load_config(config)
  
      def load_config(self, config):
          self.use_plots = config.get('use_plots', False)
          self.class_members_toctree = config.get('class_members_toctree', True)
  
      # string conversion routines
      def _str_header(self, name, symbol='`'):
          return ['.. rubric:: ' + name, '']
  
      def _str_field_list(self, name):
          return [':' + name + ':']
  
      def _str_indent(self, doc, indent=4):
          out = []
          for line in doc:
              out += [' '*indent + line]
          return out
  
      def _str_signature(self):
          return ['']
          if self['Signature']:
              return ['``%s``' % self['Signature']] + ['']
          else:
              return ['']
  
      def _str_summary(self):
          return self['Summary'] + ['']
  
      def _str_extended_summary(self):
          return self['Extended Summary'] + ['']
  
      def _str_returns(self):
          out = []
          if self['Returns']:
              out += self._str_field_list('Returns')
              out += ['']
              for param, param_type, desc in self['Returns']:
                  if param_type:
                      out += self._str_indent(['**%s** : %s' % (param.strip(),
                                                                param_type)])
                  else:
                      out += self._str_indent([param.strip()])
                  if desc:
                      out += ['']
                      out += self._str_indent(desc, 8)
                  out += ['']
          return out
  
      def _str_param_list(self, name):
          out = []
          if self[name]:
              out += self._str_field_list(name)
              out += ['']
              for param, param_type, desc in self[name]:
                  if param_type:
                      out += self._str_indent(['**%s** : %s' % (param.strip(),
                                                                param_type)])
                  else:
                      out += self._str_indent(['**%s**' % param.strip()])
                  if desc:
                      out += ['']
                      out += self._str_indent(desc, 8)
                  out += ['']
          return out
  
      @property
      def _obj(self):
          if hasattr(self, '_cls'):
              return self._cls
          elif hasattr(self, '_f'):
              return self._f
          return None
  
      def _str_member_list(self, name):
          """
          Generate a member listing, autosummary:: table where possible,
          and a table where not.
  
          """
          out = []
          if self[name]:
              out += ['.. rubric:: %s' % name, '']
              prefix = getattr(self, '_name', '')
  
              if prefix:
                  prefix = '~%s.' % prefix
  
              autosum = []
              others = []
              for param, param_type, desc in self[name]:
                  param = param.strip()
  
                  # Check if the referenced member can have a docstring or not
                  param_obj = getattr(self._obj, param, None)
                  if not (callable(param_obj)
                          or isinstance(param_obj, property)
                          or inspect.isgetsetdescriptor(param_obj)):
                      param_obj = None
  
                  if param_obj and (pydoc.getdoc(param_obj) or not desc):
                      # Referenced object has a docstring
                      autosum += ["   %s%s" % (prefix, param)]
                  else:
                      others.append((param, param_type, desc))
  
              if autosum:
                  out += ['.. autosummary::']
                  if self.class_members_toctree:
                      out += ['   :toctree:']
                  out += [''] + autosum
  
              if others:
                  maxlen_0 = max(3, max([len(x[0]) for x in others]))
                  hdr = sixu("=")*maxlen_0 + sixu("  ") + sixu("=")*10
                  fmt = sixu('%%%ds  %%s  ') % (maxlen_0,)
                  out += ['', hdr]
                  for param, param_type, desc in others:
                      desc = sixu(" ").join(x.strip() for x in desc).strip()
                      if param_type:
                          desc = "(%s) %s" % (param_type, desc)
                      out += [fmt % (param.strip(), desc)]
                  out += [hdr]
              out += ['']
          return out
  
      def _str_section(self, name):
          out = []
          if self[name]:
              out += self._str_header(name)
              out += ['']
              content = textwrap.dedent("\n".join(self[name])).split("\n")
              out += content
              out += ['']
          return out
  
      def _str_see_also(self, func_role):
          out = []
          if self['See Also']:
              see_also = super(SphinxDocString, self)._str_see_also(func_role)
              out = ['.. seealso::', '']
              out += self._str_indent(see_also[2:])
          return out
  
      def _str_warnings(self):
          out = []
          if self['Warnings']:
              out = ['.. warning::', '']
              out += self._str_indent(self['Warnings'])
          return out
  
      def _str_index(self):
          idx = self['index']
          out = []
          if len(idx) == 0:
              return out
  
          out += ['.. index:: %s' % idx.get('default','')]
          for section, references in idx.items():
              if section == 'default':
                  continue
              elif section == 'refguide':
                  out += ['   single: %s' % (', '.join(references))]
              else:
                  out += ['   %s: %s' % (section, ','.join(references))]
          return out
  
      def _str_references(self):
          out = []
          if self['References']:
              out += self._str_header('References')
              if isinstance(self['References'], str):
                  self['References'] = [self['References']]
              out.extend(self['References'])
              out += ['']
              # Latex collects all references to a separate bibliography,
              # so we need to insert links to it
              if sphinx.__version__ >= "0.6":
                  out += ['.. only:: latex','']
              else:
                  out += ['.. latexonly::','']
              items = []
              for line in self['References']:
                  m = re.match(r'.. \[([a-z0-9._-]+)\]', line, re.I)
                  if m:
                      items.append(m.group(1))
              out += ['   ' + ", ".join(["[%s]_" % item for item in items]), '']
          return out
  
      def _str_examples(self):
          examples_str = "\n".join(self['Examples'])
  
          if (self.use_plots and 'import matplotlib' in examples_str
                  and 'plot::' not in examples_str):
              out = []
              out += self._str_header('Examples')
              out += ['.. plot::', '']
              out += self._str_indent(self['Examples'])
              out += ['']
              return out
          else:
              return self._str_section('Examples')
  
      def __str__(self, indent=0, func_role="obj"):
          out = []
          out += self._str_signature()
          out += self._str_index() + ['']
          out += self._str_summary()
          out += self._str_extended_summary()
          out += self._str_param_list('Parameters')
          out += self._str_returns()
          for param_list in ('Other Parameters', 'Raises', 'Warns'):
              out += self._str_param_list(param_list)
          out += self._str_warnings()
          out += self._str_see_also(func_role)
          out += self._str_section('Notes')
          out += self._str_references()
          out += self._str_examples()
          for param_list in ('Attributes', 'Methods'):
              out += self._str_member_list(param_list)
          out = self._str_indent(out,indent)
          return '\n'.join(out)
  
  class SphinxFunctionDoc(SphinxDocString, FunctionDoc):
      def __init__(self, obj, doc=None, config={}):
          self.load_config(config)
          FunctionDoc.__init__(self, obj, doc=doc, config=config)
  
  class SphinxClassDoc(SphinxDocString, ClassDoc):
      def __init__(self, obj, doc=None, func_doc=None, config={}):
          self.load_config(config)
          ClassDoc.__init__(self, obj, doc=doc, func_doc=None, config=config)
  
  class SphinxObjDoc(SphinxDocString):
      def __init__(self, obj, doc=None, config={}):
          self._f = obj
          self.load_config(config)
          SphinxDocString.__init__(self, doc, config=config)
  
  def get_doc_object(obj, what=None, doc=None, config={}):
      if what is None:
          if inspect.isclass(obj):
              what = 'class'
          elif inspect.ismodule(obj):
              what = 'module'
          elif isinstance(obj, collections.Callable):
              what = 'function'
          else:
              what = 'object'
      if what == 'class':
          return SphinxClassDoc(obj, func_doc=SphinxFunctionDoc, doc=doc,
                                config=config)
      elif what in ('function', 'method'):
          return SphinxFunctionDoc(obj, doc=doc, config=config)
      else:
          if doc is None:
              doc = pydoc.getdoc(obj)
          return SphinxObjDoc(obj, doc, config=config)
  