Search code examples
pythonpydoc

pydoc-like program to browse content/code of Python files in a browser?


pydoc allows me to view documentation of Python modules and packages in directories added to my PYTHONPATH in a browser. Is there a way to browse the complete code of those files?

I converted Edoardo Ivanec's code using 3to2:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import with_statement
import CGIHTTPServer, SimpleHTTPServer, BaseHTTPServer
import os  
from pygments import highlight
from pygments.lexers import PythonLexer
from pygments.formatters import HtmlFormatter
from io import open

class SourceViewer(SimpleHTTPServer.SimpleHTTPRequestHandler):
    def do_GET(self):
        path = os.path.join(os.getcwdu(), self.path[1:])
        if os.path.exists(path) and path.endswith(u'.py'):
            with open(path) as file:
                code = file.read()
                hl = highlight(code, PythonLexer(), HtmlFormatter(noclasses=True, linenos=u'table'))
                self.send_response(200)
                self.end_headers()
                self.wfile.write(str(hl).encode('UTF-8'))
                return
        else:       
            super(self.__class__, self).do_GET()


if __name__ == u"__main__":
    server = BaseHTTPServer.HTTPServer((u'localhost', 8080), SourceViewer)
    server.serve_forever()

Going to localhost:8080 shows a no data received message. How should I feed it data?


Solution

  • You can extend the HTTP server in the standard library with the help of pygments to serve a highlighted and line-numbered version of the Python source files in a directory.

    This is an example for Python 3:

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    
    import http.server
    import os  
    from pygments import highlight
    from pygments.lexers import PythonLexer
    from pygments.formatters import HtmlFormatter
    
    class SourceViewer(http.server.SimpleHTTPRequestHandler):
        def do_GET(self):
            path = os.path.join(os.getcwd(), self.path[1:])
            if os.path.exists(path) and path.endswith('.py'):
                with open(path) as file:
                    code = file.read()
                    hl = highlight(code, PythonLexer(), HtmlFormatter(noclasses=True, linenos='table'))
                    self.send_response(200)
                    self.end_headers()
                    self.wfile.write(bytes(hl, 'UTF-8'))
                    return
            else:       
                super().do_GET()
    
    
    if __name__ == "__main__":
        server = http.server.HTTPServer(('localhost', 8080), SourceViewer)
        server.serve_forever()
    

    Python 2, based in your 3to2 conversion:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    from __future__ import with_statement
    import SimpleHTTPServer, BaseHTTPServer
    import os  
    from pygments import highlight
    from pygments.lexers import PythonLexer
    from pygments.formatters import HtmlFormatter
    
    class SourceViewer(SimpleHTTPServer.SimpleHTTPRequestHandler):
        def do_GET(self):
            path = os.path.join(os.getcwdu(), self.path[1:])
            if os.path.exists(path) and path.endswith(u'.py'):
                with open(path) as file:
                    code = file.read()
                    hl = highlight(code, PythonLexer(), HtmlFormatter(noclasses=True, linenos=u'table'))
                    self.send_response(200)
                    self.end_headers()
                    self.wfile.write(hl)
                    return
            else:    
                SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)
    
    if __name__ == u"__main__":
        server = BaseHTTPServer.HTTPServer((u'localhost', 8080), SourceViewer)
        server.serve_forever()
    

    And the example result:

    Example result