1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
|
# Author: David Goodger
# Contact: goodger@users.sourceforge.net
# Revision: $Revision: 3038 $
# Date: $Date: 2005-03-14 17:16:57 +0100 (Mon, 14 Mar 2005) $
# Copyright: This module has been placed in the public domain.
"""
This package contains the Python Source Reader modules.
It requires Python 2.2 or higher (`moduleparser` depends on the
`compiler` and `tokenize` modules).
"""
__docformat__ = 'reStructuredText'
import sys
import docutils.readers
from docutils.readers.python import moduleparser
from docutils import parsers
from docutils import nodes
from docutils.readers.python import pynodes
from docutils import readers
class Reader(docutils.readers.Reader):
config_section = 'python reader'
config_section_dependencies = ('readers',)
default_parser = 'restructuredtext'
def parse(self):
"""Parse `self.input` into a document tree."""
self.document = document = self.new_document()
module_section = moduleparser.parse_module(self.input,
self.source.source_path)
module_section.walk(DocformatVisitor(self.document))
visitor = DocstringFormattingVisitor(
document=document,
default_parser=self.default_parser)
module_section.walk(visitor)
self.document.append(module_section)
class DocformatVisitor(nodes.SparseNodeVisitor):
"""
This sets docformat attributes in a module. Wherever an assignment
to __docformat__ is found, we look for the enclosing scope -- a class,
a module, or a function -- and set the docformat attribute there.
We can't do this during the DocstringFormattingVisitor walking,
because __docformat__ may appear below a docstring in that format
(typically below the module docstring).
"""
def visit_attribute(self, node):
assert isinstance(node[0], pynodes.object_name)
name = node[0][0].data
if name != '__docformat__':
return
value = None
for child in children:
if isinstance(child, pynodes.expression_value):
value = child[0].data
break
assert value.startswith("'") or value.startswith('"'), "__docformat__ must be assigned a string literal (not %s); line: %s" % (value, node['lineno'])
name = name[1:-1]
looking_in = node.parent
while not isinstance(looking_in, (pynodes.module_section,
pynodes.function_section,
pynodes.class_section)):
looking_in = looking_in.parent
looking_in['docformat'] = name
class DocstringFormattingVisitor(nodes.SparseNodeVisitor):
def __init__(self, document, default_parser):
self.document = document
self.default_parser = default_parser
self.parsers = {}
def visit_docstring(self, node):
text = node[0].data
docformat = self.find_docformat(node)
del node[0]
node['docformat'] = docformat
parser = self.get_parser(docformat)
parser.parse(text, self.document)
for child in self.document.children:
node.append(child)
self.document.current_source = self.document.current_line = None
del self.document[:]
def get_parser(self, parser_name):
"""
Get a parser based on its name. We reuse parsers during this
visitation, so parser instances are cached.
"""
parser_name = parsers._parser_aliases.get(parser_name, parser_name)
if not self.parsers.has_key(parser_name):
cls = parsers.get_parser_class(parser_name)
self.parsers[parser_name] = cls()
return self.parsers[parser_name]
def find_docformat(self, node):
"""
Find the __docformat__ closest to this node (i.e., look in the
class or module)
"""
while node:
if node.get('docformat'):
return node['docformat']
node = node.parent
return self.default_parser
if __name__ == '__main__':
try:
import locale
locale.setlocale(locale.LC_ALL, '')
except:
pass
from docutils.core import publish_cmdline, default_description
description = ('Generates pseudo-XML from Python modules '
'(for testing purposes). ' + default_description)
publish_cmdline(description=description,
reader=Reader())
|