]> granicus.if.org Git - python/commitdiff
bpo-31128: Allow pydoc to bind to arbitrary hostnames (#3011)
authorFeanil Patel <feanil@edx.org>
Thu, 14 Sep 2017 21:54:09 +0000 (17:54 -0400)
committerÉric Araujo <merwok@users.noreply.github.com>
Thu, 14 Sep 2017 21:54:09 +0000 (17:54 -0400)
New -n flag allow overriding localhost with custom value,
for example to run from containers.

Doc/library/pydoc.rst
Lib/pydoc.py
Lib/test/test_pydoc.py
Misc/ACKS
Misc/NEWS.d/next/Documentation/2017-08-31.bpo-31128.uoa3cr.rst [new file with mode: 0644]

index f1bfab9a3b12740efded74ba6194c260ba4dd81e..f956b9d2176187524009069259256e64fe425997 100644 (file)
@@ -70,6 +70,12 @@ will start a HTTP server on port 1234, allowing you to browse the
 documentation at ``http://localhost:1234/`` in your preferred Web browser.
 Specifying ``0`` as the port number will select an arbitrary unused port.
 
+:program:`pydoc -n <hostname>` will start the server listening at the given
+hostname.  By default the hostname is 'localhost' but if you want the server to
+be reached from other machines, you may want to change the host name that the
+server responds to.  During development this is especially useful if you want
+to run pydoc from within a container.
+
 :program:`pydoc -b` will start the server and additionally open a web
 browser to a module index page.  Each served page has a navigation bar at the
 top where you can *Get* help on an individual item, *Search* all modules with a
@@ -98,3 +104,6 @@ Reference Manual pages.
    :mod:`pydoc` now uses :func:`inspect.signature` rather than
    :func:`inspect.getfullargspec` to extract signature information from
    callables.
+
+.. versionchanged:: 3.7
+   Added the ``-n`` option.
index 5edc77005a87140c4707f485c9cc35cffb90e545..8dc3c0ace3c94e54e28b6979a18133b72beb95c8 100644 (file)
@@ -16,12 +16,15 @@ backslash on Windows) it is treated as the path to a Python source file.
 Run "pydoc -k <keyword>" to search for a keyword in the synopsis lines
 of all available modules.
 
+Run "pydoc -n <hostname>" to start an HTTP server with the given
+hostname (default: localhost) on the local machine.
+
 Run "pydoc -p <port>" to start an HTTP server on the given port on the
 local machine.  Port number 0 can be used to get an arbitrary unused port.
 
 Run "pydoc -b" to start an HTTP server on an arbitrary unused port and
-open a Web browser to interactively browse documentation.  The -p option
-can be used with the -b option to explicitly specify the server port.
+open a Web browser to interactively browse documentation.  Combine with
+the -n and -p options to control the hostname and port used.
 
 Run "pydoc -w <name>" to write out the HTML documentation for a module
 to a file named "<name>.html".
@@ -2162,7 +2165,7 @@ def apropos(key):
 
 # --------------------------------------- enhanced Web browser interface
 
-def _start_server(urlhandler, port):
+def _start_server(urlhandler, hostname, port):
     """Start an HTTP server thread on a specific port.
 
     Start an HTML/text server thread, so HTML or text documents can be
@@ -2247,8 +2250,8 @@ def _start_server(urlhandler, port):
 
     class DocServer(http.server.HTTPServer):
 
-        def __init__(self, port, callback):
-            self.host = 'localhost'
+        def __init__(self, host, port, callback):
+            self.host = host
             self.address = (self.host, port)
             self.callback = callback
             self.base.__init__(self, self.address, self.handler)
@@ -2268,8 +2271,9 @@ def _start_server(urlhandler, port):
 
     class ServerThread(threading.Thread):
 
-        def __init__(self, urlhandler, port):
+        def __init__(self, urlhandler, host, port):
             self.urlhandler = urlhandler
+            self.host = host
             self.port = int(port)
             threading.Thread.__init__(self)
             self.serving = False
@@ -2282,7 +2286,7 @@ def _start_server(urlhandler, port):
                 DocServer.handler = DocHandler
                 DocHandler.MessageClass = email.message.Message
                 DocHandler.urlhandler = staticmethod(self.urlhandler)
-                docsvr = DocServer(self.port, self.ready)
+                docsvr = DocServer(self.host, self.port, self.ready)
                 self.docserver = docsvr
                 docsvr.serve_until_quit()
             except Exception as e:
@@ -2304,7 +2308,7 @@ def _start_server(urlhandler, port):
             self.serving = False
             self.url = None
 
-    thread = ServerThread(urlhandler, port)
+    thread = ServerThread(urlhandler, hostname, port)
     thread.start()
     # Wait until thread.serving is True to make sure we are
     # really up before returning.
@@ -2568,14 +2572,14 @@ def _url_handler(url, content_type="text/html"):
     raise TypeError('unknown content type %r for url %s' % (content_type, url))
 
 
-def browse(port=0, *, open_browser=True):
+def browse(port=0, *, open_browser=True, hostname='localhost'):
     """Start the enhanced pydoc Web server and open a Web browser.
 
     Use port '0' to start the server on an arbitrary port.
     Set open_browser to False to suppress opening a browser.
     """
     import webbrowser
-    serverthread = _start_server(_url_handler, port)
+    serverthread = _start_server(_url_handler, hostname, port)
     if serverthread.error:
         print(serverthread.error)
         return
@@ -2622,11 +2626,12 @@ def cli():
         sys.path.insert(0, '.')
 
     try:
-        opts, args = getopt.getopt(sys.argv[1:], 'bk:p:w')
+        opts, args = getopt.getopt(sys.argv[1:], 'bk:n:p:w')
         writing = False
         start_server = False
         open_browser = False
-        port = None
+        port = 0
+        hostname = 'localhost'
         for opt, val in opts:
             if opt == '-b':
                 start_server = True
@@ -2639,11 +2644,12 @@ def cli():
                 port = val
             if opt == '-w':
                 writing = True
+            if opt == '-n':
+                start_server = True
+                hostname = val
 
         if start_server:
-            if port is None:
-                port = 0
-            browse(port, open_browser=open_browser)
+            browse(port, hostname=hostname, open_browser=open_browser)
             return
 
         if not args: raise BadUsage
@@ -2679,14 +2685,17 @@ def cli():
 {cmd} -k <keyword>
     Search for a keyword in the synopsis lines of all available modules.
 
+{cmd} -n <hostname>
+    Start an HTTP server with the given hostname (default: localhost).
+
 {cmd} -p <port>
     Start an HTTP server on the given port on the local machine.  Port
     number 0 can be used to get an arbitrary unused port.
 
 {cmd} -b
     Start an HTTP server on an arbitrary unused port and open a Web browser
-    to interactively browse documentation.  The -p option can be used with
-    the -b option to explicitly specify the server port.
+    to interactively browse documentation.  This option can be used in
+    combination with -n and/or -p.
 
 {cmd} -w <name> ...
     Write out the HTML documentation for a module to a file in the current
index 1ac08edb48e8a4107c3cb6b9e61d400e5524d21d..52830b49aea31f8be2ed55d09a7bde3bedc7e83d 100644 (file)
@@ -909,8 +909,8 @@ class PydocServerTest(unittest.TestCase):
             text = 'the URL sent was: (%s, %s)' % (url, content_type)
             return text
 
-        serverthread = pydoc._start_server(my_url_handler, port=0)
-        self.assertIn('localhost', serverthread.docserver.address)
+        serverthread = pydoc._start_server(my_url_handler, hostname='0.0.0.0', port=0)
+        self.assertIn('0.0.0.0', serverthread.docserver.address)
 
         starttime = time.time()
         timeout = 1  #seconds
index 462a74eb0566d4b772b4fefca032e535132a50af..0f6ac7d898a17b74d2468b38f64d134d2ed52128 100644 (file)
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -1177,6 +1177,7 @@ Claude Paroz
 Heikki Partanen
 Harri Pasanen
 Gaël Pasgrimaud
+Feanil Patel
 Ashish Nitin Patil
 Alecsandru Patrascu
 Randy Pausch
diff --git a/Misc/NEWS.d/next/Documentation/2017-08-31.bpo-31128.uoa3cr.rst b/Misc/NEWS.d/next/Documentation/2017-08-31.bpo-31128.uoa3cr.rst
new file mode 100644 (file)
index 0000000..480ec6b
--- /dev/null
@@ -0,0 +1 @@
+Allow the pydoc server to bind to arbitrary hostnames.