diff options
Diffstat (limited to 'Lib/pydoc.py')
-rwxr-xr-x | Lib/pydoc.py | 289 |
1 files changed, 7 insertions, 282 deletions
diff --git a/Lib/pydoc.py b/Lib/pydoc.py index d0c6f62..caae46a 100755 --- a/Lib/pydoc.py +++ b/Lib/pydoc.py @@ -22,11 +22,6 @@ 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. -For platforms without a command line, "pydoc -g" starts the HTTP server -and also pops up a little window for controlling it. This option is -deprecated, since the server can now be controlled directly from HTTP -clients. - Run "pydoc -w <name>" to write out the HTML documentation for a module to a file named "<name>.html". @@ -42,7 +37,6 @@ __all__ = ['help'] __author__ = "Ka-Ping Yee <ping@lfw.org>" __date__ = "26 February 2001" -__version__ = "$Revision$" __credits__ = """Guido van Rossum, for an excellent programming language. Tommy Burnette, the original creator of manpy. Paul Prescod, for all his work on onlinehelp. @@ -169,11 +163,11 @@ def _split_list(s, predicate): def visiblename(name, all=None, obj=None): """Decide whether to show documentation on a variable.""" # Certain special names are redundant. - _hidden_names = ('__builtins__', '__doc__', '__file__', '__path__', + if name in {'__builtins__', '__doc__', '__file__', '__path__', '__module__', '__name__', '__slots__', '__package__', '__cached__', '__author__', '__credits__', '__date__', - '__version__') - if name in _hidden_names: return 0 + '__version__'}: + return 0 # Private names are hidden, but special names are displayed. if name.startswith('__') and name.endswith('__'): return 1 # Namedtuples have public fields and methods with a single leading underscore @@ -951,6 +945,9 @@ class HTMLDoc(Doc): modpkgs = [] if shadowed is None: shadowed = {} for importer, name, ispkg in pkgutil.iter_modules([dir]): + if any((0xD800 <= ord(ch) <= 0xDFFF) for ch in name): + # ignore a module if its name contains a surrogate character + continue modpkgs.append((name, '', ispkg, name in shadowed)) shadowed[name] = 1 @@ -2054,272 +2051,6 @@ def apropos(key): warnings.filterwarnings('ignore') # ignore problems during import ModuleScanner().run(callback, key, onerror=onerror) -# --------------------------------------------------- Web browser interface - -def serve(port, callback=None, completer=None): - import http.server, email.message, select - - msg = 'the pydoc.serve() function is deprecated' - warnings.warn(msg, DeprecationWarning, stacklevel=2) - - class DocHandler(http.server.BaseHTTPRequestHandler): - def send_document(self, title, contents): - try: - self.send_response(200) - self.send_header('Content-Type', 'text/html; charset=UTF-8') - self.end_headers() - self.wfile.write(html.page(title, contents).encode('utf-8')) - except IOError: pass - - def do_GET(self): - path = self.path - if path[-5:] == '.html': path = path[:-5] - if path[:1] == '/': path = path[1:] - if path and path != '.': - try: - obj = locate(path, forceload=1) - except ErrorDuringImport as value: - self.send_document(path, html.escape(str(value))) - return - if obj: - self.send_document(describe(obj), html.document(obj, path)) - else: - self.send_document(path, -'no Python documentation found for %s' % repr(path)) - else: - heading = html.heading( -'<big><big><strong>Python: Index of Modules</strong></big></big>', -'#ffffff', '#7799ee') - def bltinlink(name): - return '<a href="%s.html">%s</a>' % (name, name) - names = [x for x in sys.builtin_module_names if x != '__main__'] - contents = html.multicolumn(names, bltinlink) - indices = ['<p>' + html.bigsection( - 'Built-in Modules', '#ffffff', '#ee77aa', contents)] - - seen = {} - for dir in sys.path: - indices.append(html.index(dir, seen)) - contents = heading + ' '.join(indices) + '''<p align=right> -<font color="#909090" face="helvetica, arial"><strong> -pydoc</strong> by Ka-Ping Yee <ping@lfw.org></font>''' - self.send_document('Index of Modules', contents) - - def log_message(self, *args): pass - - class DocServer(http.server.HTTPServer): - def __init__(self, port, callback): - host = 'localhost' - self.address = (host, port) - self.url = 'http://%s:%d/' % (host, port) - self.callback = callback - self.base.__init__(self, self.address, self.handler) - - def serve_until_quit(self): - import select - self.quit = False - while not self.quit: - rd, wr, ex = select.select([self.socket.fileno()], [], [], 1) - if rd: self.handle_request() - self.server_close() - - def server_activate(self): - self.base.server_activate(self) - if self.callback: self.callback(self) - - DocServer.base = http.server.HTTPServer - DocServer.handler = DocHandler - DocHandler.MessageClass = email.message.Message - try: - try: - DocServer(port, callback).serve_until_quit() - except (KeyboardInterrupt, select.error): - pass - finally: - if completer: completer() - -# ----------------------------------------------------- graphical interface - -def gui(): - """Graphical interface (starts Web server and pops up a control window).""" - - msg = ('the pydoc.gui() function and "pydoc -g" option are deprecated\n', - 'use "pydoc.browse() function and "pydoc -b" option instead.') - warnings.warn(msg, DeprecationWarning, stacklevel=2) - - class GUI: - def __init__(self, window, port=7464): - self.window = window - self.server = None - self.scanner = None - - import tkinter - self.server_frm = tkinter.Frame(window) - self.title_lbl = tkinter.Label(self.server_frm, - text='Starting server...\n ') - self.open_btn = tkinter.Button(self.server_frm, - text='open browser', command=self.open, state='disabled') - self.quit_btn = tkinter.Button(self.server_frm, - text='quit serving', command=self.quit, state='disabled') - - self.search_frm = tkinter.Frame(window) - self.search_lbl = tkinter.Label(self.search_frm, text='Search for') - self.search_ent = tkinter.Entry(self.search_frm) - self.search_ent.bind('<Return>', self.search) - self.stop_btn = tkinter.Button(self.search_frm, - text='stop', pady=0, command=self.stop, state='disabled') - if sys.platform == 'win32': - # Trying to hide and show this button crashes under Windows. - self.stop_btn.pack(side='right') - - self.window.title('pydoc') - self.window.protocol('WM_DELETE_WINDOW', self.quit) - self.title_lbl.pack(side='top', fill='x') - self.open_btn.pack(side='left', fill='x', expand=1) - self.quit_btn.pack(side='right', fill='x', expand=1) - self.server_frm.pack(side='top', fill='x') - - self.search_lbl.pack(side='left') - self.search_ent.pack(side='right', fill='x', expand=1) - self.search_frm.pack(side='top', fill='x') - self.search_ent.focus_set() - - font = ('helvetica', sys.platform == 'win32' and 8 or 10) - self.result_lst = tkinter.Listbox(window, font=font, height=6) - self.result_lst.bind('<Button-1>', self.select) - self.result_lst.bind('<Double-Button-1>', self.goto) - self.result_scr = tkinter.Scrollbar(window, - orient='vertical', command=self.result_lst.yview) - self.result_lst.config(yscrollcommand=self.result_scr.set) - - self.result_frm = tkinter.Frame(window) - self.goto_btn = tkinter.Button(self.result_frm, - text='go to selected', command=self.goto) - self.hide_btn = tkinter.Button(self.result_frm, - text='hide results', command=self.hide) - self.goto_btn.pack(side='left', fill='x', expand=1) - self.hide_btn.pack(side='right', fill='x', expand=1) - - self.window.update() - self.minwidth = self.window.winfo_width() - self.minheight = self.window.winfo_height() - self.bigminheight = (self.server_frm.winfo_reqheight() + - self.search_frm.winfo_reqheight() + - self.result_lst.winfo_reqheight() + - self.result_frm.winfo_reqheight()) - self.bigwidth, self.bigheight = self.minwidth, self.bigminheight - self.expanded = 0 - self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight)) - self.window.wm_minsize(self.minwidth, self.minheight) - self.window.tk.willdispatch() - - import threading - threading.Thread( - target=serve, args=(port, self.ready, self.quit)).start() - - def ready(self, server): - self.server = server - self.title_lbl.config( - text='Python documentation server at\n' + server.url) - self.open_btn.config(state='normal') - self.quit_btn.config(state='normal') - - def open(self, event=None, url=None): - url = url or self.server.url - import webbrowser - webbrowser.open(url) - - def quit(self, event=None): - if self.server: - self.server.quit = 1 - self.window.quit() - - def search(self, event=None): - key = self.search_ent.get() - self.stop_btn.pack(side='right') - self.stop_btn.config(state='normal') - self.search_lbl.config(text='Searching for "%s"...' % key) - self.search_ent.forget() - self.search_lbl.pack(side='left') - self.result_lst.delete(0, 'end') - self.goto_btn.config(state='disabled') - self.expand() - - import threading - if self.scanner: - self.scanner.quit = 1 - self.scanner = ModuleScanner() - threading.Thread(target=self.scanner.run, - args=(self.update, key, self.done)).start() - - def update(self, path, modname, desc): - if modname[-9:] == '.__init__': - modname = modname[:-9] + ' (package)' - self.result_lst.insert('end', - modname + ' - ' + (desc or '(no description)')) - - def stop(self, event=None): - if self.scanner: - self.scanner.quit = 1 - self.scanner = None - - def done(self): - self.scanner = None - self.search_lbl.config(text='Search for') - self.search_lbl.pack(side='left') - self.search_ent.pack(side='right', fill='x', expand=1) - if sys.platform != 'win32': self.stop_btn.forget() - self.stop_btn.config(state='disabled') - - def select(self, event=None): - self.goto_btn.config(state='normal') - - def goto(self, event=None): - selection = self.result_lst.curselection() - if selection: - modname = self.result_lst.get(selection[0]).split()[0] - self.open(url=self.server.url + modname + '.html') - - def collapse(self): - if not self.expanded: return - self.result_frm.forget() - self.result_scr.forget() - self.result_lst.forget() - self.bigwidth = self.window.winfo_width() - self.bigheight = self.window.winfo_height() - self.window.wm_geometry('%dx%d' % (self.minwidth, self.minheight)) - self.window.wm_minsize(self.minwidth, self.minheight) - self.expanded = 0 - - def expand(self): - if self.expanded: return - self.result_frm.pack(side='bottom', fill='x') - self.result_scr.pack(side='right', fill='y') - self.result_lst.pack(side='top', fill='both', expand=1) - self.window.wm_geometry('%dx%d' % (self.bigwidth, self.bigheight)) - self.window.wm_minsize(self.minwidth, self.bigminheight) - self.expanded = 1 - - def hide(self, event=None): - self.stop() - self.collapse() - - import tkinter - try: - root = tkinter.Tk() - # Tk will crash if pythonw.exe has an XP .manifest - # file and the root has is not destroyed explicitly. - # If the problem is ever fixed in Tk, the explicit - # destroy can go. - try: - gui = GUI(root) - root.mainloop() - finally: - root.destroy() - except KeyboardInterrupt: - pass - - # --------------------------------------- enhanced Web browser interface def _start_server(urlhandler, port): @@ -2776,15 +2507,12 @@ def cli(): sys.path.insert(0, '.') try: - opts, args = getopt.getopt(sys.argv[1:], 'bgk:p:w') + opts, args = getopt.getopt(sys.argv[1:], 'bk:p:w') writing = False start_server = False open_browser = False port = None for opt, val in opts: - if opt == '-g': - gui() - return if opt == '-b': start_server = True open_browser = True @@ -2845,9 +2573,6 @@ def cli(): to interactively browse documentation. The -p option can be used with the -b option to explicitly specify the server port. -{cmd} -g - Deprecated. - {cmd} -w <name> ... Write out the HTML documentation for a module to a file in the current directory. If <name> contains a '{sep}', it is treated as a filename; if |