diff options
Diffstat (limited to 'Lib/test/test_pydoc.py')
-rw-r--r-- | Lib/test/test_pydoc.py | 189 |
1 files changed, 157 insertions, 32 deletions
diff --git a/Lib/test/test_pydoc.py b/Lib/test/test_pydoc.py index f7aa487580c..92f79636cd0 100644 --- a/Lib/test/test_pydoc.py +++ b/Lib/test/test_pydoc.py @@ -1,21 +1,29 @@ -import sys import os -import os.path +import sys import difflib -import subprocess -import re -import pydoc import inspect -import unittest +import pydoc +import re +import string +import subprocess import test.support +import time +import unittest import xml.etree +import textwrap +from io import StringIO +from collections import namedtuple from contextlib import contextmanager -from test.support import TESTFN, forget, rmtree, EnvironmentVarGuard +from test.support import TESTFN, forget, rmtree, EnvironmentVarGuard, \ + reap_children, captured_output, captured_stdout from test import pydoc_mod -expected_text_pattern = \ -""" +# Just in case sys.modules["test"] has the optional attribute __loader__. +if hasattr(pydoc_mod, "__loader__"): + del pydoc_mod.__loader__ + +expected_text_pattern = """ NAME test.pydoc_mod - This is a test module for test_pydoc %s @@ -80,8 +88,7 @@ FILE %s """.strip() -expected_html_pattern = \ -""" +expected_html_pattern = """ <table width="100%%" cellspacing=0 cellpadding=2 border=0 summary="heading"> <tr bgcolor="#7799ee"> <td valign=bottom> <br> @@ -177,7 +184,7 @@ war</tt></dd></dl> \x20\x20\x20\x20 <tr><td bgcolor="#7799ee"><tt> </tt></td><td> </td> <td width="100%%">Nobody</td></tr></table> -""".strip() +""".strip() # ' <- emacs turd # output pattern for missing module @@ -192,8 +199,11 @@ def run_pydoc(module_name, *args): output of pydoc. """ cmd = [sys.executable, pydoc.__file__, " ".join(args), module_name] - output = subprocess.Popen(cmd, stdout=subprocess.PIPE).stdout.read() - return output.strip() + try: + output = subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0] + return output.strip() + finally: + reap_children() def get_pydoc_html(module): "Returns pydoc generated output as html" @@ -213,22 +223,32 @@ def get_pydoc_text(module): output = doc.docmodule(module) - # cleanup the extra text formatting that pydoc preforms + # clean up the extra text formatting that pydoc performs patt = re.compile('\b.') output = patt.sub('', output) return output.strip(), loc def print_diffs(text1, text2): "Prints unified diffs for two texts" + # XXX now obsolete, use unittest built-in support lines1 = text1.splitlines(True) lines2 = text2.splitlines(True) diffs = difflib.unified_diff(lines1, lines2, n=0, fromfile='expected', tofile='got') print('\n' + ''.join(diffs)) +def get_html_title(text): + # Bit of hack, but good enough for test purposes + header, _, _ = text.partition("</head>") + _, _, title = header.partition("<title>") + title, _, _ = title.partition("</title>") + return title -class PyDocDocTest(unittest.TestCase): +class PydocDocTest(unittest.TestCase): + + @unittest.skipIf(sys.flags.optimize >= 2, + "Docstrings are omitted with -O2 and above") def test_html_doc(self): result, doc_loc = get_pydoc_html(pydoc_mod) mod_file = inspect.getabsfile(pydoc_mod) @@ -242,6 +262,8 @@ class PyDocDocTest(unittest.TestCase): print_diffs(expected_html, result) self.fail("outputs are not equal, see diff above") + @unittest.skipIf(sys.flags.optimize >= 2, + "Docstrings are omitted with -O2 and above") def test_text_doc(self): result, doc_loc = get_pydoc_text(pydoc_mod) expected_text = expected_text_pattern % \ @@ -271,7 +293,8 @@ class PyDocDocTest(unittest.TestCase): ('i_am_not_here', 'i_am_not_here'), ('test.i_am_not_here_either', 'i_am_not_here_either'), ('test.i_am_not_here.neither_am_i', 'i_am_not_here.neither_am_i'), - ('i_am_not_here.{}'.format(modname), 'i_am_not_here.{}'.format(modname)), + ('i_am_not_here.{}'.format(modname), + 'i_am_not_here.{}'.format(modname)), ('test.{}'.format(modname), modname), ) @@ -288,9 +311,8 @@ class PyDocDocTest(unittest.TestCase): fullmodname = os.path.join(TESTFN, modname) sourcefn = fullmodname + os.extsep + "py" for importstring, expectedinmsg in testpairs: - f = open(sourcefn, 'w') - f.write("import {}\n".format(importstring)) - f.close() + with open(sourcefn, 'w') as f: + f.write("import {}\n".format(importstring)) try: result = run_pydoc(modname).decode("ascii") finally: @@ -317,6 +339,50 @@ class PyDocDocTest(unittest.TestCase): self.assertEqual(stripid("<type 'exceptions.Exception'>"), "<type 'exceptions.Exception'>") + @unittest.skipIf(sys.flags.optimize >= 2, + 'Docstrings are omitted with -O2 and above') + def test_help_output_redirect(self): + # issue 940286, if output is set in Helper, then all output from + # Helper.help should be redirected + old_pattern = expected_text_pattern + getpager_old = pydoc.getpager + getpager_new = lambda: (lambda x: x) + self.maxDiff = None + + buf = StringIO() + helper = pydoc.Helper(output=buf) + unused, doc_loc = get_pydoc_text(pydoc_mod) + module = "test.pydoc_mod" + help_header = """ + Help on module test.pydoc_mod in test: + + """.lstrip() + help_header = textwrap.dedent(help_header) + expected_help_pattern = help_header + expected_text_pattern + + pydoc.getpager = getpager_new + try: + with captured_output('stdout') as output, \ + captured_output('stderr') as err: + helper.help(module) + result = buf.getvalue().strip() + expected_text = expected_help_pattern % \ + (doc_loc, inspect.getabsfile(pydoc_mod)) + self.assertEqual('', output.getvalue()) + self.assertEqual('', err.getvalue()) + self.assertEqual(expected_text, result) + finally: + pydoc.getpager = getpager_old + + def test_namedtuple_public_underscore(self): + NT = namedtuple('NT', ['abc', 'def'], rename=True) + with captured_stdout() as help_io: + help(NT) + helptext = help_io.getvalue() + self.assertIn('_1', helptext) + self.assertIn('_replace', helptext) + self.assertIn('_asdict', helptext) + class TestDescriptions(unittest.TestCase): @@ -324,28 +390,87 @@ class TestDescriptions(unittest.TestCase): # Check that pydocfodder module can be described from test import pydocfodder doc = pydoc.render_doc(pydocfodder) - self.assertTrue("pydocfodder" in doc) - - def test_classic_class(self): - class C: "Classic class" - c = C() - self.assertEqual(pydoc.describe(C), 'class C') - self.assertEqual(pydoc.describe(c), 'C') - expected = 'C in module %s' % __name__ - self.assertTrue(expected in pydoc.render_doc(c)) + self.assertIn("pydocfodder", doc) def test_class(self): - class C(object): "New-style class" + class C: "New-style class" c = C() self.assertEqual(pydoc.describe(C), 'class C') self.assertEqual(pydoc.describe(c), 'C') expected = 'C in module %s object' % __name__ - self.assertTrue(expected in pydoc.render_doc(c)) + self.assertIn(expected, pydoc.render_doc(c)) + + +class PydocServerTest(unittest.TestCase): + """Tests for pydoc._start_server""" + + def test_server(self): + + # Minimal test that starts the server, then stops it. + def my_url_handler(url, content_type): + text = 'the URL sent was: (%s, %s)' % (url, content_type) + return text + + serverthread = pydoc._start_server(my_url_handler, port=0) + starttime = time.time() + timeout = 1 #seconds + + while serverthread.serving: + time.sleep(.01) + if serverthread.serving and time.time() - starttime > timeout: + serverthread.stop() + break + + self.assertEqual(serverthread.error, None) + + +class PydocUrlHandlerTest(unittest.TestCase): + """Tests for pydoc._url_handler""" + + def test_content_type_err(self): + f = pydoc._url_handler + self.assertRaises(TypeError, f, 'A', '') + self.assertRaises(TypeError, f, 'B', 'foobar') + + def test_url_requests(self): + # Test for the correct title in the html pages returned. + # This tests the different parts of the URL handler without + # getting too picky about the exact html. + requests = [ + ("", "Pydoc: Index of Modules"), + ("get?key=", "Pydoc: Index of Modules"), + ("index", "Pydoc: Index of Modules"), + ("topics", "Pydoc: Topics"), + ("keywords", "Pydoc: Keywords"), + ("pydoc", "Pydoc: module pydoc"), + ("get?key=pydoc", "Pydoc: module pydoc"), + ("search?key=pydoc", "Pydoc: Search Results"), + ("topic?key=def", "Pydoc: KEYWORD def"), + ("topic?key=STRINGS", "Pydoc: TOPIC STRINGS"), + ("foobar", "Pydoc: Error - foobar"), + ("getfile?key=foobar", "Pydoc: Error - getfile?key=foobar"), + ] + + for url, title in requests: + text = pydoc._url_handler(url, "text/html") + result = get_html_title(text) + self.assertEqual(result, title) + + path = string.__file__ + title = "Pydoc: getfile " + path + url = "getfile?key=" + path + text = pydoc._url_handler(url, "text/html") + result = get_html_title(text) + self.assertEqual(result, title) def test_main(): - test.support.run_unittest(PyDocDocTest, TestDescriptions) + test.support.run_unittest(PydocDocTest, + TestDescriptions, + PydocServerTest, + PydocUrlHandlerTest, + ) if __name__ == "__main__": test_main() |