Package epydoc :: Package test :: Module util |
[hide private]
[frames] | no frames]

# Source Code for Module epydoc.test.util

      1  #
      2  # epydoc -- Utility functions used by regression tests (*.doctest)
      3  # Edward Loper
      4  #
      5  # Created [01/30/01 05:18 PM]
      6  # $Id: html.py 1420 2007-01-28 14:19:30Z dvarrazzo $
      7  #
      8
      9  """
     10  Utility functions used by the regression tests (C{*.doctest}).
     11  """
     12  __docformat__ = 'epytext en'
     13
     14  import tempfile, re, os, os.path, textwrap, sys
     15  from epydoc.docbuilder import build_doc, build_doc_index
     16  from epydoc.docparser import parse_docs
     17  from epydoc.docintrospecter import introspect_docs
     18  from epydoc.apidoc import ClassDoc, RoutineDoc
     19  from epydoc.markup import ParsedDocstring
     20  from epydoc.docwriter.html import HTMLWriter
     21
     22  ######################################################################
     23  #{ Test Functions
     24  ######################################################################
     25
     26 -def buildvaluedoc(s):
     27      """
     28      This test function takes a string containing the contents of a
     29      module.  It writes the string contents to a file, imports the file
     30      as a module, and uses build_doc to build documentation, and
     31      returns it as a C{ValueDoc} object.
     32      """
     33      tmp_dir = write_pystring_to_tmp_dir(s)
     34      val_doc = build_doc(os.path.join(tmp_dir, 'epydoc_test.py'))
     35      cleanup_tmp_dir(tmp_dir)
     36      return val_doc
     37
     38 -def runbuilder(s, attribs='', build=None, exclude=''):
     39      """
     40      This test function takes a string containing the contents of a
     41      module.  It writes the string contents to a file, imports the file
     42      as a module, and uses build_doc to build documentation, and pretty
     43      prints the resulting ModuleDoc object.  The C{attribs} argument
     44      specifies which attributes of the C{APIDoc}s should be displayed.
     45      The C{build} argument gives the name of a variable in the module
     46      whose documentation should be built, instead of bilding docs for
     47      the whole module.
     48      """
     49      # Write it to a temp file.
     50      tmp_dir = write_pystring_to_tmp_dir(s)
     51      # Build it.
     52      val_doc = build_doc(os.path.join(tmp_dir, 'epydoc_test.py'))
     53      if build: val_doc = val_doc.variables[build].value
     54      # Display it.
     55      if isinstance(val_doc, ClassDoc):
     56          for val in val_doc.variables.values():
     57              if isinstance(val.value, RoutineDoc):
     58                  fun_to_plain(val.value)
     59      s = val_doc.pp(include=attribs.split(),exclude=exclude.split())
     60      s = re.sub(r"(filename = ).*", r"\1...", s)
     61      s = re.sub(r"(<module 'epydoc_test' from ).*", r'\1...', s)
     62      s = re.sub(r"(<function \w+ at )0x\w+>", r"\1...>", s)
     63      s = re.sub(r"(<\w+ object at )0x\w+>", r"\1...>", s)
     64      print s
     65      # Clean up.
     66      cleanup_tmp_dir(tmp_dir)
     67
     68 -def runparser(s, attribs='', show=None, exclude=''):
     69      """
     70      This test function takes a string containing the contents of a
     71      module, and writes it to a file, uses `parse_docs` to parse it,
     72      and pretty prints the resulting ModuleDoc object.  The `attribs`
     73      argument specifies which attributes of the `APIDoc`s should be
     74      displayed.  The `show` argument, if specifies, gives the name of
     75      the object in the module that should be displayed (but the whole
     76      module will always be inspected; this just selects what to
     77      display).
     78      """
     79      # Write it to a temp file.
     80      tmp_dir = write_pystring_to_tmp_dir(s)
     81      # Parse it.
     82      val_doc = parse_docs(os.path.join(tmp_dir, 'epydoc_test.py'))
     83      if show is not None:
     84          for name in show.split('.'):
     85              if isinstance(val_doc, ClassDoc):
     86                  val_doc = val_doc.local_variables[name].value
     87              else:
     88                  val_doc = val_doc.variables[name].value
     89      # Display it.
     90      s = val_doc.pp(include=attribs.split(), exclude=exclude.split())
     91      s = re.sub(r"filename = .*", "filename = ...", s)
     92      print s
     93      # Clean up.
     94      cleanup_tmp_dir(tmp_dir)
     95
     96 -def runintrospecter(s, attribs='', introspect=None, exclude=''):
     97      """
     98      This test function takes a string containing the contents of a
     99      module.  It writes the string contents to a file, imports the file
    100      as a module, and uses C{introspect_docs} to introspect it, and
    101      pretty prints the resulting ModuleDoc object.  The C{attribs}
    102      argument specifies which attributes of the C{APIDoc}s should be
    103      displayed.  The C{introspect} argument gives the name of a variable
    104      in the module whose value should be introspected, instead of
    105      introspecting the whole module.
    106      """
    107      # Write it to a temp file.
    108      tmp_dir = write_pystring_to_tmp_dir(s)
    109      # Import it.
    110      sys.path.insert(0, tmp_dir)
    111      if introspect is None:
    112          import epydoc_test as val
    113      else:
    114          exec("from epydoc_test import %s as val" % introspect)
    115      del sys.path[0]
    116      # Introspect it.
    117      val_doc = introspect_docs(val)
    118      # Display it.
    119      s = val_doc.pp(include=attribs.split(),exclude=exclude.split())
    120      s = re.sub(r"(filename = ).*", r"\1...", s)
    121      s = re.sub(r"(<module 'epydoc_test' from ).*", r'\1...', s)
    122      s = re.sub(r"(<function \w+ at )0x\w+>", r"\1...>", s)
    123      s = re.sub(r"(<\w+ object at )0x\w+>", r"\1...>", s)
    124      print s
    125      # Clean up.
    126      cleanup_tmp_dir(tmp_dir)
    127
    128 -def print_warnings():
    129      """
    130      Register a logger that will print warnings & errors.
    131      """
    132      from epydoc import log
    133      del log._loggers[:]
    134      log.register_logger(log.SimpleLogger(log.DOCSTRING_WARNING))
    135
    136 -def testencoding(s, introspect=True, parse=True, debug=False):
    137      """
    138      An end-to-end test for unicode encodings.  This function takes a
    139      given string, writes it to a python file, and processes that
    140      file's documentation.  It then generates HTML output from the
    141      documentation, extracts all docstrings from the generated HTML
    142      output, and displays them.  (In order to extract & display all
    143      docstrings, it monkey-patches the HMTLwriter.docstring_to_html()
    144      method.)"""
    145      # Monkey-patch docstring_to_html
    146      original_docstring_to_html = HTMLWriter.docstring_to_html
    147      HTMLWriter.docstring_to_html = print_docstring_as_html
    148
    149      # Write s to a temporary file.
    150      tmp_dir = tempfile.mkdtemp()
    151      path = os.path.join(tmp_dir, 'enc_test.py')
    152      out = open(path, 'w')
    153      out.write(textwrap.dedent(s))
    154      out.close()
    155      # Build docs for it
    156      docindex = build_doc_index([path], introspect, parse)
    157      if docindex is None: return
    158      sys.modules.pop('enc_test', None)
    159      # Write html output.
    160      writer = HTMLWriter(docindex, mark_docstrings=True)
    161      writer.write(tmp_dir)
    162      for file in os.listdir(tmp_dir):
    163          os.unlink(os.path.join(tmp_dir,file))
    164      os.rmdir(tmp_dir)
    165
    166      # Restore the HTMLWriter class to its original state.
    167      HTMLWriter.docstring_to_html = original_docstring_to_html
    168
    169  ######################################################################
    170  #{ Helper Functions
    171  ######################################################################
    172
    173 -def write_pystring_to_tmp_dir(s):
    174      tmp_dir = tempfile.mkdtemp()
    175      out = open(os.path.join(tmp_dir, 'epydoc_test.py'), 'w')
    176      out.write(textwrap.dedent(s))
    177      out.close()
    178      return tmp_dir
    179
    180 -def cleanup_tmp_dir(tmp_dir):
    181      os.unlink(os.path.join(tmp_dir, 'epydoc_test.py'))
    182      try: os.unlink(os.path.join(tmp_dir, 'epydoc_test.pyc'))
    183      except OSError: pass
    184      os.rmdir(tmp_dir)
    185      sys.modules.pop('epydoc_test', None)
    186
    187 -def to_plain(docstring):
    188      """Conver a parsed docstring into plain text"""
    189      if isinstance(docstring, ParsedDocstring):
    190          docstring = docstring.to_plaintext(None)
    191      return docstring.rstrip()
    192
    193 -def fun_to_plain(val_doc):
    194      """Convert parsed docstrings in text from a RoutineDoc"""
    195      for k, v in val_doc.arg_types.items():
    196          val_doc.arg_types[k] = to_plain(v)
    197      for i, (k, v) in enumerate(val_doc.arg_descrs):
    198          val_doc.arg_descrs[i] = (k, to_plain(v))
    199
    200 -def print_docstring_as_html(self, parsed_docstring, *varargs, **kwargs):
    201      """
    202      Convert the given parsed_docstring to HTML and print it.  Ignore
    203      any other arguments.  This function is used by L{testencoding} to
    204      monkey-patch the HTMLWriter class's docstring_to_html() method.
    205      """
    206      s = parsed_docstring.to_html(None).strip()
    207      s = s.encode('ascii', 'xmlcharrefreplace')
    208      s = remove_surrogates(s)
    209      print s
    210      return ''
    211
    212 -def remove_surrogates(s):
    213      """
    214      The following is a helper function, used to convert two-character
    215      surrogate sequences into single characters.  This is needed
    216      because some systems create surrogates but others don't.
    217      """
    218      pieces = re.split('(&#\d+;)', s)
    219      for i in range(3, len(pieces)-1, 2):
    220          if pieces[i-1] != '': continue
    221          high,low = int(pieces[i-2][2:-1]), int(pieces[i][2:-1])
    222          if 0xd800 <= high <= 0xdbff and 0xdc00 <= low <= 0xdfff:
    223              pieces[i-2] = '&#%d;' % (((high&0x3ff)<<10) +
    224                                       (low&0x3ff) + 0x10000)
    225              pieces[i] = ''
    226      return ''.join(pieces)
    227