1
2
3
4
5
6
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
24
25
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
50 tmp_dir = write_pystring_to_tmp_dir(s)
51
52 val_doc = build_doc(os.path.join(tmp_dir, 'epydoc_test.py'))
53 if build: val_doc = val_doc.variables[build].value
54
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
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
80 tmp_dir = write_pystring_to_tmp_dir(s)
81
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
90 s = val_doc.pp(include=attribs.split(), exclude=exclude.split())
91 s = re.sub(r"filename = .*", "filename = ...", s)
92 print s
93
94 cleanup_tmp_dir(tmp_dir)
95
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
108 tmp_dir = write_pystring_to_tmp_dir(s)
109
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
117 val_doc = introspect_docs(val)
118
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
126 cleanup_tmp_dir(tmp_dir)
127
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
146 original_docstring_to_html = HTMLWriter.docstring_to_html
147 HTMLWriter.docstring_to_html = print_docstring_as_html
148
149
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
156 docindex = build_doc_index([path], introspect, parse)
157 if docindex is None: return
158 sys.modules.pop('enc_test', None)
159
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
167 HTMLWriter.docstring_to_html = original_docstring_to_html
168
169
170
171
172
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
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
192
199
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
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