blob: 04cfa70e365c24c4042a0014c79fed33e4643a37 [file] [log] [blame]
Georg Brandl8632cc22008-05-18 16:32:48 +00001import sys
2import difflib
3import subprocess
4import re
5import pydoc
Georg Brandlb7e419e2008-05-20 08:10:03 +00006import inspect
Georg Brandl8632cc22008-05-18 16:32:48 +00007import unittest
8import test.test_support
Benjamin Petersonf5c38da2008-05-18 20:48:07 +00009
Georg Brandl8632cc22008-05-18 16:32:48 +000010from test import pydoc_mod
11
12expected_text_pattern = \
13"""
14NAME
15 test.pydoc_mod - This is a test module for test_pydoc
16
17FILE
18 %s
19
20CLASSES
21 __builtin__.object
22 B
23 A
24\x20\x20\x20\x20
25 class A
26 | Hello and goodbye
27 |\x20\x20
28 | Methods defined here:
29 |\x20\x20
30 | __init__()
31 | Wow, I have no function!
32\x20\x20\x20\x20
33 class B(__builtin__.object)
34 | Data descriptors defined here:
35 |\x20\x20
36 | __dict__
37 | dictionary for instance variables (if defined)
38 |\x20\x20
39 | __weakref__
40 | list of weak references to the object (if defined)
41 |\x20\x20
42 | ----------------------------------------------------------------------
43 | Data and other attributes defined here:
44 |\x20\x20
45 | NO_MEANING = 'eggs'
46
47FUNCTIONS
48 doc_func()
49 This function solves all of the world's problems:
50 hunger
51 lack of Python
52 war
53\x20\x20\x20\x20
54 nodoc_func()
55
56DATA
57 __author__ = 'Benjamin Peterson'
58 __credits__ = 'Nobody'
59 __package__ = None
60 __version__ = '1.2.3.4'
61
62VERSION
63 1.2.3.4
64
65AUTHOR
66 Benjamin Peterson
67
68CREDITS
69 Nobody
70""".strip()
71
72expected_html_pattern = \
73"""
74<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
75<tr bgcolor="#7799ee">
76<td valign=bottom>&nbsp;<br>
77<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="test.html"><font color="#ffffff">test</font></a>.pydoc_mod</strong></big></big> (version 1.2.3.4)</font></td
78><td align=right valign=bottom
79><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:%s">%s</a></font></td></tr></table>
80 <p><tt>This&nbsp;is&nbsp;a&nbsp;test&nbsp;module&nbsp;for&nbsp;test_pydoc</tt></p>
81<p>
82<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
83<tr bgcolor="#ee77aa">
84<td colspan=3 valign=bottom>&nbsp;<br>
85<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
86\x20\x20\x20\x20
87<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
88<td width="100%%"><dl>
89<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
90</font></dt><dd>
91<dl>
92<dt><font face="helvetica, arial"><a href="test.pydoc_mod.html#B">B</a>
93</font></dt></dl>
94</dd>
95<dt><font face="helvetica, arial"><a href="test.pydoc_mod.html#A">A</a>
96</font></dt></dl>
97 <p>
98<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
99<tr bgcolor="#ffc8d8">
100<td colspan=3 valign=bottom>&nbsp;<br>
101<font color="#000000" face="helvetica, arial"><a name="A">class <strong>A</strong></a></font></td></tr>
102\x20\x20\x20\x20
103<tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
104<td colspan=2><tt>Hello&nbsp;and&nbsp;goodbye<br>&nbsp;</tt></td></tr>
105<tr><td>&nbsp;</td>
106<td width="100%%">Methods defined here:<br>
107<dl><dt><a name="A-__init__"><strong>__init__</strong></a>()</dt><dd><tt>Wow,&nbsp;I&nbsp;have&nbsp;no&nbsp;function!</tt></dd></dl>
108
109</td></tr></table> <p>
110<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
111<tr bgcolor="#ffc8d8">
112<td colspan=3 valign=bottom>&nbsp;<br>
113<font color="#000000" face="helvetica, arial"><a name="B">class <strong>B</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
114\x20\x20\x20\x20
115<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
116<td width="100%%">Data descriptors defined here:<br>
117<dl><dt><strong>__dict__</strong></dt>
118<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
119</dl>
120<dl><dt><strong>__weakref__</strong></dt>
121<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
122</dl>
123<hr>
124Data and other attributes defined here:<br>
125<dl><dt><strong>NO_MEANING</strong> = 'eggs'</dl>
126
127</td></tr></table></td></tr></table><p>
128<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
129<tr bgcolor="#eeaa77">
130<td colspan=3 valign=bottom>&nbsp;<br>
131<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
132\x20\x20\x20\x20
133<tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
134<td width="100%%"><dl><dt><a name="-doc_func"><strong>doc_func</strong></a>()</dt><dd><tt>This&nbsp;function&nbsp;solves&nbsp;all&nbsp;of&nbsp;the&nbsp;world's&nbsp;problems:<br>
135hunger<br>
136lack&nbsp;of&nbsp;Python<br>
137war</tt></dd></dl>
138 <dl><dt><a name="-nodoc_func"><strong>nodoc_func</strong></a>()</dt></dl>
139</td></tr></table><p>
140<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
141<tr bgcolor="#55aa55">
142<td colspan=3 valign=bottom>&nbsp;<br>
143<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
144\x20\x20\x20\x20
145<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
146<td width="100%%"><strong>__author__</strong> = 'Benjamin Peterson'<br>
147<strong>__credits__</strong> = 'Nobody'<br>
148<strong>__package__</strong> = None<br>
149<strong>__version__</strong> = '1.2.3.4'</td></tr></table><p>
150<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
151<tr bgcolor="#7799ee">
152<td colspan=3 valign=bottom>&nbsp;<br>
153<font color="#ffffff" face="helvetica, arial"><big><strong>Author</strong></big></font></td></tr>
154\x20\x20\x20\x20
155<tr><td bgcolor="#7799ee"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
156<td width="100%%">Benjamin&nbsp;Peterson</td></tr></table><p>
157<table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
158<tr bgcolor="#7799ee">
159<td colspan=3 valign=bottom>&nbsp;<br>
160<font color="#ffffff" face="helvetica, arial"><big><strong>Credits</strong></big></font></td></tr>
161\x20\x20\x20\x20
162<tr><td bgcolor="#7799ee"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
163<td width="100%%">Nobody</td></tr></table>
164""".strip()
165
166# output pattern for missing module
167missing_pattern = "no Python documentation found for '%s'"
168
169def run_pydoc(module_name, *args):
170 """
171 Runs pydoc on the specified module. Returns the stripped
172 output of pydoc.
173 """
174 cmd = [sys.executable, pydoc.__file__, " ".join(args), module_name]
175 output = subprocess.Popen(cmd, stdout=subprocess.PIPE).stdout.read()
176 return output.strip()
177
178def get_pydoc_html(module):
179 "Returns pydoc generated output as html"
180 output = pydoc.HTMLDoc().docmodule(module)
181 return output.strip()
182
183def get_pydoc_text(module):
184 "Returns pydoc generated output as text"
185 output = pydoc.TextDoc().docmodule(module)
186
187 # cleanup the extra text formatting that pydoc preforms
188 patt = re.compile('\b.')
189 output = patt.sub('', output)
190 return output.strip()
191
192def print_diffs(text1, text2):
193 "Prints unified diffs for two texts"
Georg Brandlfb3de1f2008-05-20 08:07:36 +0000194 lines1 = text1.splitlines(True)
195 lines2 = text2.splitlines(True)
196 diffs = difflib.unified_diff(lines1, lines2, n=0, fromfile='expected',
197 tofile='got')
198 print '\n' + ''.join(diffs)
Georg Brandl8632cc22008-05-18 16:32:48 +0000199
Georg Brandl8632cc22008-05-18 16:32:48 +0000200
Georg Brandl8632cc22008-05-18 16:32:48 +0000201class PyDocDocTest(unittest.TestCase):
202
203 def test_html_doc(self):
204 result = get_pydoc_html(pydoc_mod)
Georg Brandlb7e419e2008-05-20 08:10:03 +0000205 mod_file = inspect.getabsfile(pydoc_mod)
Georg Brandl8632cc22008-05-18 16:32:48 +0000206 expected_html = expected_html_pattern % (mod_file, mod_file)
207 if result != expected_html:
Georg Brandlfb3de1f2008-05-20 08:07:36 +0000208 print_diffs(expected_html, result)
Georg Brandl8632cc22008-05-18 16:32:48 +0000209 self.fail("outputs are not equal, see diff above")
210
211 def test_text_doc(self):
212 result = get_pydoc_text(pydoc_mod)
Georg Brandlb7e419e2008-05-20 08:10:03 +0000213 expected_text = expected_text_pattern % inspect.getabsfile(pydoc_mod)
Georg Brandl8632cc22008-05-18 16:32:48 +0000214 if result != expected_text:
Georg Brandlfb3de1f2008-05-20 08:07:36 +0000215 print_diffs(expected_text, result)
Georg Brandl8632cc22008-05-18 16:32:48 +0000216 self.fail("outputs are not equal, see diff above")
217
Benjamin Petersonf5c38da2008-05-18 20:48:07 +0000218 def test_not_here(self):
219 missing_module = "test.i_am_not_here"
220 result = run_pydoc(missing_module)
221 expected = missing_pattern % missing_module
222 self.assertEqual(expected, result,
223 "documentation for missing module found")
224
Georg Brandl8632cc22008-05-18 16:32:48 +0000225
226class TestDescriptions(unittest.TestCase):
Benjamin Petersonf5c38da2008-05-18 20:48:07 +0000227
Georg Brandl8632cc22008-05-18 16:32:48 +0000228 def test_module(self):
229 # Check that pydocfodder module can be described
230 from test import pydocfodder
231 doc = pydoc.render_doc(pydocfodder)
Benjamin Petersonf5c38da2008-05-18 20:48:07 +0000232 self.assert_("pydocfodder" in doc)
Georg Brandl8632cc22008-05-18 16:32:48 +0000233
234 def test_classic_class(self):
235 class C: "Classic class"
236 c = C()
Benjamin Petersonf5c38da2008-05-18 20:48:07 +0000237 self.assertEqual(pydoc.describe(C), 'class C')
238 self.assertEqual(pydoc.describe(c), 'instance of C')
239 self.assert_('instance of C in module test.test_pydoc'
Georg Brandl8632cc22008-05-18 16:32:48 +0000240 in pydoc.render_doc(c))
241
242 def test_class(self):
243 class C(object): "New-style class"
244 c = C()
245
Benjamin Petersonf5c38da2008-05-18 20:48:07 +0000246 self.assertEqual(pydoc.describe(C), 'class C')
247 self.assertEqual(pydoc.describe(c), 'C')
248 self.assert_('C in module test.test_pydoc object'
Georg Brandl8632cc22008-05-18 16:32:48 +0000249 in pydoc.render_doc(c))
250
251
252def test_main():
Benjamin Petersonf5c38da2008-05-18 20:48:07 +0000253 test.test_support.run_unittest(PyDocDocTest,
Georg Brandl8632cc22008-05-18 16:32:48 +0000254 TestDescriptions)
255
256if __name__ == "__main__":
257 test_main()