[Python-checkins] bpo-31128: Allow pydoc to bind to arbitrary hostnames (#3011)
Éric Araujo
webhook-mailer at python.org
Thu Sep 14 17:54:12 EDT 2017
https://github.com/python/cpython/commit/6a396c9807b1674a24e240731f18e20de97117a5
commit: 6a396c9807b1674a24e240731f18e20de97117a5
branch: master
author: Feanil Patel <feanil at edx.org>
committer: Éric Araujo <merwok at users.noreply.github.com>
date: 2017-09-14T17:54:09-04:00
summary:
bpo-31128: Allow pydoc to bind to arbitrary hostnames (#3011)
New -n flag allow overriding localhost with custom value,
for example to run from containers.
files:
A Misc/NEWS.d/next/Documentation/2017-08-31.bpo-31128.uoa3cr.rst
M Doc/library/pydoc.rst
M Lib/pydoc.py
M Lib/test/test_pydoc.py
M Misc/ACKS
diff --git a/Doc/library/pydoc.rst b/Doc/library/pydoc.rst
index f1bfab9a3b1..f956b9d2176 100644
--- a/Doc/library/pydoc.rst
+++ b/Doc/library/pydoc.rst
@@ -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.
diff --git a/Lib/pydoc.py b/Lib/pydoc.py
index 5edc77005a8..8dc3c0ace3c 100644
--- a/Lib/pydoc.py
+++ b/Lib/pydoc.py
@@ -16,12 +16,15 @@ class or function within a module or module in a package. If the
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 onerror(modname):
# --------------------------------------- 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 log_message(self, *args):
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 server_activate(self):
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 run(self):
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 stop(self):
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 get_html_page(url):
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 @@ class BadUsage(Exception): pass
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 @@ class BadUsage(Exception): pass
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 @@ class BadUsage(Exception): pass
{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
diff --git a/Lib/test/test_pydoc.py b/Lib/test/test_pydoc.py
index 1ac08edb48e..52830b49aea 100644
--- a/Lib/test/test_pydoc.py
+++ b/Lib/test/test_pydoc.py
@@ -909,8 +909,8 @@ 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)
- 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
diff --git a/Misc/ACKS b/Misc/ACKS
index 462a74eb056..0f6ac7d898a 100644
--- 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
index 00000000000..480ec6b2869
--- /dev/null
+++ b/Misc/NEWS.d/next/Documentation/2017-08-31.bpo-31128.uoa3cr.rst
@@ -0,0 +1 @@
+Allow the pydoc server to bind to arbitrary hostnames.
More information about the Python-checkins
mailing list