PageRenderTime 66ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/lib-python/modified-2.7/test/test_pydoc.py

https://bitbucket.org/evelyn559/pypy
Python | 367 lines | 323 code | 8 blank | 36 comment | 1 complexity | 059889b6b002290651430f24d16004f8 MD5 | raw file
  1. import sys
  2. import os
  3. import os.path
  4. import difflib
  5. import subprocess
  6. import re
  7. import pydoc
  8. import inspect
  9. import keyword
  10. import unittest
  11. import xml.etree
  12. import test.test_support
  13. from contextlib import contextmanager
  14. from collections import namedtuple
  15. from test.test_support import (
  16. TESTFN, forget, rmtree, EnvironmentVarGuard, reap_children, captured_stdout)
  17. from test import pydoc_mod
  18. expected_text_pattern = \
  19. """
  20. NAME
  21. test.pydoc_mod - This is a test module for test_pydoc
  22. FILE
  23. %s
  24. %s
  25. CLASSES
  26. __builtin__.object
  27. B
  28. A
  29. \x20\x20\x20\x20
  30. class A
  31. | Hello and goodbye
  32. |\x20\x20
  33. | Methods defined here:
  34. |\x20\x20
  35. | __init__()
  36. | Wow, I have no function!
  37. \x20\x20\x20\x20
  38. class B(__builtin__.object)
  39. | Data descriptors defined here:
  40. |\x20\x20
  41. | __dict__
  42. | dictionary for instance variables (if defined)
  43. |\x20\x20
  44. | __weakref__
  45. | list of weak references to the object (if defined)
  46. |\x20\x20
  47. | ----------------------------------------------------------------------
  48. | Data and other attributes defined here:
  49. |\x20\x20
  50. | NO_MEANING = 'eggs'
  51. FUNCTIONS
  52. doc_func()
  53. This function solves all of the world's problems:
  54. hunger
  55. lack of Python
  56. war
  57. \x20\x20\x20\x20
  58. nodoc_func()
  59. DATA
  60. __author__ = 'Benjamin Peterson'
  61. __credits__ = 'Nobody'
  62. __version__ = '1.2.3.4'
  63. VERSION
  64. 1.2.3.4
  65. AUTHOR
  66. Benjamin Peterson
  67. CREDITS
  68. Nobody
  69. """.strip()
  70. expected_html_pattern = \
  71. """
  72. <table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading">
  73. <tr bgcolor="#7799ee">
  74. <td valign=bottom>&nbsp;<br>
  75. <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
  76. ><td align=right valign=bottom
  77. ><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:%s">%s</a>%s</font></td></tr></table>
  78. <p><tt>This&nbsp;is&nbsp;a&nbsp;test&nbsp;module&nbsp;for&nbsp;test_pydoc</tt></p>
  79. <p>
  80. <table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
  81. <tr bgcolor="#ee77aa">
  82. <td colspan=3 valign=bottom>&nbsp;<br>
  83. <font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
  84. \x20\x20\x20\x20
  85. <tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
  86. <td width="100%%"><dl>
  87. <dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
  88. </font></dt><dd>
  89. <dl>
  90. <dt><font face="helvetica, arial"><a href="test.pydoc_mod.html#B">B</a>
  91. </font></dt></dl>
  92. </dd>
  93. <dt><font face="helvetica, arial"><a href="test.pydoc_mod.html#A">A</a>
  94. </font></dt></dl>
  95. <p>
  96. <table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
  97. <tr bgcolor="#ffc8d8">
  98. <td colspan=3 valign=bottom>&nbsp;<br>
  99. <font color="#000000" face="helvetica, arial"><a name="A">class <strong>A</strong></a></font></td></tr>
  100. \x20\x20\x20\x20
  101. <tr bgcolor="#ffc8d8"><td rowspan=2><tt>&nbsp;&nbsp;&nbsp;</tt></td>
  102. <td colspan=2><tt>Hello&nbsp;and&nbsp;goodbye<br>&nbsp;</tt></td></tr>
  103. <tr><td>&nbsp;</td>
  104. <td width="100%%">Methods defined here:<br>
  105. <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>
  106. </td></tr></table> <p>
  107. <table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
  108. <tr bgcolor="#ffc8d8">
  109. <td colspan=3 valign=bottom>&nbsp;<br>
  110. <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>
  111. \x20\x20\x20\x20
  112. <tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
  113. <td width="100%%">Data descriptors defined here:<br>
  114. <dl><dt><strong>__dict__</strong></dt>
  115. <dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
  116. </dl>
  117. <dl><dt><strong>__weakref__</strong></dt>
  118. <dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
  119. </dl>
  120. <hr>
  121. Data and other attributes defined here:<br>
  122. <dl><dt><strong>NO_MEANING</strong> = 'eggs'</dl>
  123. </td></tr></table></td></tr></table><p>
  124. <table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
  125. <tr bgcolor="#eeaa77">
  126. <td colspan=3 valign=bottom>&nbsp;<br>
  127. <font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
  128. \x20\x20\x20\x20
  129. <tr><td bgcolor="#eeaa77"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
  130. <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>
  131. hunger<br>
  132. lack&nbsp;of&nbsp;Python<br>
  133. war</tt></dd></dl>
  134. <dl><dt><a name="-nodoc_func"><strong>nodoc_func</strong></a>()</dt></dl>
  135. </td></tr></table><p>
  136. <table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
  137. <tr bgcolor="#55aa55">
  138. <td colspan=3 valign=bottom>&nbsp;<br>
  139. <font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
  140. \x20\x20\x20\x20
  141. <tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
  142. <td width="100%%"><strong>__author__</strong> = 'Benjamin Peterson'<br>
  143. <strong>__credits__</strong> = 'Nobody'<br>
  144. <strong>__version__</strong> = '1.2.3.4'</td></tr></table><p>
  145. <table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
  146. <tr bgcolor="#7799ee">
  147. <td colspan=3 valign=bottom>&nbsp;<br>
  148. <font color="#ffffff" face="helvetica, arial"><big><strong>Author</strong></big></font></td></tr>
  149. \x20\x20\x20\x20
  150. <tr><td bgcolor="#7799ee"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
  151. <td width="100%%">Benjamin&nbsp;Peterson</td></tr></table><p>
  152. <table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="section">
  153. <tr bgcolor="#7799ee">
  154. <td colspan=3 valign=bottom>&nbsp;<br>
  155. <font color="#ffffff" face="helvetica, arial"><big><strong>Credits</strong></big></font></td></tr>
  156. \x20\x20\x20\x20
  157. <tr><td bgcolor="#7799ee"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
  158. <td width="100%%">Nobody</td></tr></table>
  159. """.strip()
  160. # output pattern for missing module
  161. missing_pattern = "no Python documentation found for '%s'"
  162. # output pattern for module with bad imports
  163. badimport_pattern = "problem in %s - <type 'exceptions.ImportError'>: No module named %s"
  164. def run_pydoc(module_name, *args):
  165. """
  166. Runs pydoc on the specified module. Returns the stripped
  167. output of pydoc.
  168. """
  169. cmd = [sys.executable, pydoc.__file__, " ".join(args), module_name]
  170. try:
  171. output = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0]
  172. return output.strip()
  173. finally:
  174. reap_children()
  175. def get_pydoc_html(module):
  176. "Returns pydoc generated output as html"
  177. doc = pydoc.HTMLDoc()
  178. output = doc.docmodule(module)
  179. loc = doc.getdocloc(pydoc_mod) or ""
  180. if loc:
  181. loc = "<br><a href=\"" + loc + "\">Module Docs</a>"
  182. return output.strip(), loc
  183. def get_pydoc_text(module):
  184. "Returns pydoc generated output as text"
  185. doc = pydoc.TextDoc()
  186. loc = doc.getdocloc(pydoc_mod) or ""
  187. if loc:
  188. loc = "\nMODULE DOCS\n " + loc + "\n"
  189. output = doc.docmodule(module)
  190. # cleanup the extra text formatting that pydoc preforms
  191. patt = re.compile('\b.')
  192. output = patt.sub('', output)
  193. return output.strip(), loc
  194. def print_diffs(text1, text2):
  195. "Prints unified diffs for two texts"
  196. lines1 = text1.splitlines(True)
  197. lines2 = text2.splitlines(True)
  198. diffs = difflib.unified_diff(lines1, lines2, n=0, fromfile='expected',
  199. tofile='got')
  200. print '\n' + ''.join(diffs)
  201. class PyDocDocTest(unittest.TestCase):
  202. @unittest.skipIf(sys.flags.optimize >= 2,
  203. "Docstrings are omitted with -O2 and above")
  204. def test_html_doc(self):
  205. result, doc_loc = get_pydoc_html(pydoc_mod)
  206. mod_file = inspect.getabsfile(pydoc_mod)
  207. if sys.platform == 'win32':
  208. import nturl2path
  209. mod_url = nturl2path.pathname2url(mod_file)
  210. else:
  211. mod_url = mod_file
  212. expected_html = expected_html_pattern % (mod_url, mod_file, doc_loc)
  213. if result != expected_html:
  214. print_diffs(expected_html, result)
  215. self.fail("outputs are not equal, see diff above")
  216. @unittest.skipIf(sys.flags.optimize >= 2,
  217. "Docstrings are omitted with -O2 and above")
  218. def test_text_doc(self):
  219. result, doc_loc = get_pydoc_text(pydoc_mod)
  220. expected_text = expected_text_pattern % \
  221. (inspect.getabsfile(pydoc_mod), doc_loc)
  222. if result != expected_text:
  223. print_diffs(expected_text, result)
  224. self.fail("outputs are not equal, see diff above")
  225. def test_issue8225(self):
  226. # Test issue8225 to ensure no doc link appears for xml.etree
  227. result, doc_loc = get_pydoc_text(xml.etree)
  228. self.assertEqual(doc_loc, "", "MODULE DOCS incorrectly includes a link")
  229. def test_not_here(self):
  230. missing_module = "test.i_am_not_here"
  231. result = run_pydoc(missing_module)
  232. expected = missing_pattern % missing_module
  233. self.assertEqual(expected, result,
  234. "documentation for missing module found")
  235. def test_badimport(self):
  236. # This tests the fix for issue 5230, where if pydoc found the module
  237. # but the module had an internal import error pydoc would report no doc
  238. # found.
  239. modname = 'testmod_xyzzy'
  240. testpairs = (
  241. ('i_am_not_here', 'i_am_not_here'),
  242. ('test.i_am_not_here_either', 'i_am_not_here_either'),
  243. ('test.i_am_not_here.neither_am_i', 'i_am_not_here'),
  244. ('i_am_not_here.{}'.format(modname), 'i_am_not_here'),
  245. ('test.{}'.format(modname), modname),
  246. )
  247. @contextmanager
  248. def newdirinpath(dir):
  249. os.mkdir(dir)
  250. sys.path.insert(0, dir)
  251. yield
  252. sys.path.pop(0)
  253. rmtree(dir)
  254. with newdirinpath(TESTFN), EnvironmentVarGuard() as env:
  255. env['PYTHONPATH'] = TESTFN
  256. fullmodname = os.path.join(TESTFN, modname)
  257. sourcefn = fullmodname + os.extsep + "py"
  258. for importstring, expectedinmsg in testpairs:
  259. f = open(sourcefn, 'w')
  260. f.write("import {}\n".format(importstring))
  261. f.close()
  262. try:
  263. result = run_pydoc(modname)
  264. finally:
  265. forget(modname)
  266. expected = badimport_pattern % (modname, '(.+\\.)?' + expectedinmsg + '(\\..+)?$')
  267. self.assertTrue(re.match(expected, result))
  268. def test_input_strip(self):
  269. missing_module = " test.i_am_not_here "
  270. result = run_pydoc(missing_module)
  271. expected = missing_pattern % missing_module.strip()
  272. self.assertEqual(expected, result,
  273. "white space was not stripped from module name "
  274. "or other error output mismatch")
  275. def test_stripid(self):
  276. # test with strings, other implementations might have different repr()
  277. stripid = pydoc.stripid
  278. # strip the id
  279. self.assertEqual(stripid('<function stripid at 0x88dcee4>'),
  280. '<function stripid>')
  281. self.assertEqual(stripid('<function stripid at 0x01F65390>'),
  282. '<function stripid>')
  283. # nothing to strip, return the same text
  284. self.assertEqual(stripid('42'), '42')
  285. self.assertEqual(stripid("<type 'exceptions.Exception'>"),
  286. "<type 'exceptions.Exception'>")
  287. class TestDescriptions(unittest.TestCase):
  288. def test_module(self):
  289. # Check that pydocfodder module can be described
  290. from test import pydocfodder
  291. doc = pydoc.render_doc(pydocfodder)
  292. self.assertIn("pydocfodder", doc)
  293. def test_classic_class(self):
  294. class C: "Classic class"
  295. c = C()
  296. self.assertEqual(pydoc.describe(C), 'class C')
  297. self.assertEqual(pydoc.describe(c), 'instance of C')
  298. expected = 'instance of C in module %s' % __name__
  299. self.assertIn(expected, pydoc.render_doc(c))
  300. def test_class(self):
  301. class C(object): "New-style class"
  302. c = C()
  303. self.assertEqual(pydoc.describe(C), 'class C')
  304. self.assertEqual(pydoc.describe(c), 'C')
  305. expected = 'C in module %s object' % __name__
  306. self.assertIn(expected, pydoc.render_doc(c))
  307. def test_namedtuple_public_underscore(self):
  308. NT = namedtuple('NT', ['abc', 'def'], rename=True)
  309. with captured_stdout() as help_io:
  310. help(NT)
  311. helptext = help_io.getvalue()
  312. self.assertIn('_1', helptext)
  313. self.assertIn('_replace', helptext)
  314. self.assertIn('_asdict', helptext)
  315. class TestHelper(unittest.TestCase):
  316. def test_keywords(self):
  317. self.assertEqual(sorted(pydoc.Helper.keywords),
  318. sorted(keyword.kwlist))
  319. def test_main():
  320. test.test_support.run_unittest(PyDocDocTest,
  321. TestDescriptions,
  322. TestHelper)
  323. if __name__ == "__main__":
  324. test_main()